Skip to main content

Full text of "Amiga 3D Graphic Programming in BASIC"

See other formats


010 1, 



iHHnM 




rilfefflcfe llli tloit El till tWitllWi 



the spectacular and powerful 
graphic capabilities of the Amiga 




A Data Becker Boo 



Amiga 

3D Graphic 

Programming 

in BASIC 



Jennrich 

Massmann 

Schulz 




A Data Becker Book 
Published by 



Abacus 



iiwwmn 



First Printing, February 1989 

Printed in U.S.A. 

Copyright © 1987, 1988 Data Becker GmbH 

MerowingerstraBe 30 
4000 Dusseldorf, West Germany 

Copyright © 1989 Abacus 

5370 52nd Street, SE 
Grand Rapids, MI 49508 

This book is copyrighted. No part of this book may be reproduced, stored in a retrieval 
system, or transmitted in any form or by any means, electronic, mechanical, photocopying, 
recording or otherwise, without the prior written permission of Abacus or Data Becker 
GmbH. 

Every effort has been made to ensure complete and accurate information concerning the 
material presented in this book. However, Abacus can neither guarantee nor be held legally 
responsible for any mistakes in printing or faulty instructions contained in this book. The 
authors always appreciate receiving notice of any errors or misprints. 

Amiga 500, Amiga 1000, Amiga 2000 and Amiga are trademarks or registered trademarks of 
Commodore- Amiga, Inc. AC/BASIC Compiler and AC/BASIC are trademarks or registered 
trademarks of Absoft Corporation. Cray is a trademark or registered trademark of Cray 
Incorporated. AmigaB ASIC is a trademark or registered trademark of Microsoft Corporation. 

ISBN 1-55755-044-1 



Table of Contents 



1. Introduction 1 

2. The Basics of Ray Tracing 5 

2.1 Natural Objects 7 

2.2 In the Computer 8 

2.2.1 Light and Darkness 8 

2.2.2 Shadows 9 

2.2.3 Reflection 9 

2.2.4 Transparency 10 

2.2.5 Limitations 10 

2.3 Presentation in the Computer 11 

2.3.1 Data Structure 16 

2.4 Simulating Perception 19 

2.4.1 What Do You See? 22 

2.4.2 What You Should See 31 

2.4.3 The Dark Side of the World 37 

2.4.4 Reflection 38 

2.4.5 Bringing Color to the Screen 40 

2.5 Optimization 44 

3. The Tracer Program 49 

3.1 Wire Models 51 

3.1.1 From 3D to 2D 51 

3.1.2 Objects and Surfaces 61 

3.2 The Editor 74 

3.2.1 Why an Editor? 74 

3.2.2 The Tasks Required of the Editor 75 

3.2.3 Individual Components of the Editor 78 

3.2.3.1 The Input 78 

3.2.3.2 The Output 86 

3.2.3.3 The Graphics 89 

3.2.3.4 Data Operations 92 

3.2.3.5 Disk Operations 96 

3.2.3.6 Mouse and Gadgets 98 

3.2.4 Tips on Writing an Editor 102 

3.3 The Main Program 104 

3.3.1 The Remaining Tracer Routines 104 

3.3.2 Merging Tracer Modules into one Program 141 

4. Using the Program 143 

4.1 Editor Documentation 145 

4.1.1 Input — General Information 145 

4.1.2 Entering Object Data 146 

4.1.3 The Operations Menu 152 

4.1.4 The Material Editor 152 

4.1.5 The Transform Menu 153 



4.1.6 The Disk Menu 154 

4.2 Tracer Documentation 155 

4.2.1 After Starting 155 

4.2.2 Amiga Menu 156 

4.2.3 File Menu 156 

4.2.3.1 Loading and Saving Objects 156 

4.2.3.2 Loading Materials 157 

4.2.3.3 Background 157 

4.2.3.4 Saving Graphics 158 

4.2.3.5 Printing Graphics 158 

4.2.3.6 Setting New Colors 159 

4.2.3.7 Leaving the Program 159 

4.2.4 The Editor Menu 159 

4.2.5 The Parameter Menu 160 

4.2.6 The Draw Menu 161 

4.2.6.1 Shadows 161 

4.2.6.2 The Wire Model 162 

4.2.7 Keyboard Program Control 163 

5. Program Enhancements 165 

6. 3D Tricks and Tips 171 

7. Mathematical Basics 177 

7.1 Vectors 179 

7.2 Using Vectors 182 

7.3 Angles Between Two Vectors 184 

7.4 Intersecting Lines and Planes 187 

8. The Optional Disk 191 

8.1 Compiling the Programs 194 

8.1.1 Compiling the Editor 194 

8.1.2 Compiling the Tracer 196 

Appendices 201 

A. Modules of the Tracer 203 

B. The Tracer Program 207 

C. The Editor Program 302 

D. The SetPoint Program 345 

E. Tracer Error Messages 356 

Index 357 



IV 



1. 

Introduction 



Abacus 1. Introduction 



Introduction 



The Amiga is a truly amazing machine, especially when it's used for 
graphics. Most Amiga users, when asked why they bought their 
Amiga, reply, "Great graphics." The picture on the cover of this book 
was generated using the editor and tracer programs listed at the end of 
this book. This shows some of the Amiga's graphic capabilities. This 
book will help you explore programming 3D graphic ray tracing on 
your Amiga, using the computer language that came with your Amiga 
— AmigaBASIC. 

There is one thing we should mention before starting. Programming 
three dimensional graphics requires a knowledge of mathematics. There- 
fore, this book has a mathematical basis. If you don't know much 
about math, don't panic. We'll do our best to explain the subject to you 
in understandable terms. When you finish reading this book you'll 
know more about the subject than you did before you read the book. 

You'll need basic math skills to use this book — but you won't need a 
PhD in math. Many of the equations involved in computing three 
dimensional figures may not make much sense to you. To help these 
make sense, we've placed many explanations of the mathematical 
equations alongside the sample programs and program descriptions. 

The programs presented in this book, tracer and editor, are very large. A 
complete listing of each of the programs can be found in the 
appendices. Ray tracing requires many math calculations, which can be 
very slow when done in BASIC. We recommend that the programs 
presented in this book be compiled for maximum speed. The programs 
should only be compiled after complete testing has been done in 
BASIC. Chapter 8 describes the changes required to compile the 
programs using the AC/BASIC® compiler. 

The optional disk available for this book also contains the complete 
program modules in ASCII format and versions compiled using 
AC/BASIC®. The disk also contains two example pictures created with 
the programs. The important individual routines are described through 
the course of the book, but you should refer to the complete listing 
when entering the programs. 



1. Introduction Amiga 3D Graphic Programming 



Before going on to the main part of this book, there are two terms 
you'll see throughout this book — ray tracing and algorithms. These 
may not sound familiar to you if you're studying 3D graphics for the 
first time, so we'll define the two of them now: 

Ray tracing There are a number of methods used in generating three dimensional 

defined graphics on computers. Ray tracing traces the effects of light rays 

which shine on an object or group of objects. Since ray tracing has its 

basis in actual light and optical calculation, it reproduces the object's 

surfaces and qualities (e.g., shadows, colors, reflectivity, transparency). 

Many programmers consider this the best method of 3D graphic 
reproduction, because ray tiacing produces very lifelike effects. The 
photograph on the cover of this book is a result of ray tracing, and the 
entire book discusses the subject of ray tracing in AmigaB ASIC. 

Algorithms This is a common buzzword in computing. An algorithm describes a 

plan for solving a problem, usually using a computer program. This 
book, for example, lists algorithms for performing such tasks as 
drawing geometric figures on a computer screen, then adding data to 
these figures that will implement shadows, color, etc. 



2. 

The Basics of 

Ray Tracing 



Abacus 



2. The Basics of Ray Tracing 



2. 



The Basics of Ray Tracing 



Hidden surface 
algorithms 



Hidden line Computer graphics of any kind look great on the Amiga. But three 

algorithms dimensional computer representations of familiar objects are fantastic. 

String art graphics are a very simple example of 3D graphics. A 
computer can go one step further and display only the visible lines of a 
3D graphic. Hidden line algorithms display the visible surfaces only. 
The results achieved using hidden line algorithms are very good. 
However, hidden line algorithms make it difficult to remove objects or 
to display objects covered by other objects. 

Hidden surface algorithms are used when you want more realistic graph- 
ics. The object is represented by many small triangles. These triangles 
can be arranged so the the ones furthest away are shown first and the 
closest are shown last. This gives a display with invisible surfaces. The 
best presentation occurs when the triangles are a very small distance 
apart. Hidden surface algorithms also can display the illusion of shad- 
ows (e.g., when a bright light is shone on an object's surface). 

Ray tracing Ray tracing algorithms are a step beyond hidden surface algorithms. 

algorithms Ray tracing gets its name from tracing the effects of light rays shining 

on an object. Unlike hidden surface and hidden line algorithms, ray 
tracing allows the calculation of shadows, reflection and transparency of 
objects. The result of a graphic generated from ray tracing requires more 
calculation time than hidden line or hidden surface graphics, but the 
finished graphic looks much more realistic. 

The basics of ray tracing are pretty simple. You won't have to devote 
your life to the study of mathematics to understand and use them. 



2.1 



Natural Objects 



Before we go on to develop a ray tracing algorithm, we must first take 
a look at objects and how they appear in the real world. Imagine a green 
cube lit by the sun. The cube absorbs all light rays in colors other than 
green, and reflects all the green light rays back to your eyes. 

As each light ray enters your eyes, you see a green point of light 
coming from the direction of the cube. Because the sun (the light 
source) sends out light rays that reflect off the cube, your eye receives 
an image (graphic) of how the cube looks. 



2. The Basics of Ray Tracing 



Amiga 3D Graphic Programming 



2.2 



In the Computer 



Visual rays 



To duplicate the green cube as a computer generated 3D object, you 
must get past some obstacles. First, your computer has only one visual 
receptor (the screen) to replace your two eyes. In addition, the light 
source is very low powered — it simulates light as a small group of 
pixels on the screen. Our own sun sends out an extremely large number 
of light rays: So many that all the computers on this planet couldn't 
reproduce this phenomenon in a reasonable amount of time. 

Your eye sets the visible light rays coming from the green cube. The 
visible light rays reflect the cube's color, and send this information to 
your eyes. You see this information because your eye is sensitive to 
light rays and can receive the reflected colors. 

The computer screen uses visual rays rather than the visible light rays 
available to us. The computer must calculate each visual ray and 
determine whether this ray came from the surface of an object, and from 
which direction the visual ray came. If the ray bounced off an object, 
the computer must determine the color. The ray then appears on the 
screen as a pixel, just as a retina reads light rays. Your eyes receive 
light rays through lenses. The following figure shows the eye's concept 
of an image, then a computer's ray tracing view of the same image: 



Figure 2.1 




iNat-nrall 



«-*Snn 1 



F^ I Light rays| 

I Lens I 

pomputer modelj 





iLine of slqht| 



2.2.1 



Light and darkness 



Think of our imaginary green cube in the form of a computer image, 
based on the data presented so far. Right now all you really have on the 
screen is the green outline of what could be a cube. One important 
factor in ray tracing makes an image three dimensional: Shading. If you 
think of a real cube lit by the sun, the sides most directly exposed to 
light are brighter than those sides less directly lit. The more 



Abacus 2.2 In the Computer 



perpendicular that you place a light source to a side, the brighter that 
side appears. 

It isn't hard to program the computer to understand the brightness of a 
side. The same calculations can determine whether the side of an object 
faces toward or away from the light source. 



2.2.2 Shadows 



The computer model becomes really interesting if it includes shadows 
that a real object might cast. Shadows occur when an object blocks the 
path of light rays. Imagine our sunlit cube again. The cube interrupts 
the sunlight's path as it travels toward the base on which the cube 
stands. This interruption appears on the base as a shadow. 

Visual rays calculate the computer model instead of actual light rays. 
Therefore, we need to tackle the problem in a different manner. Imagine 
that you are wearing a light source placed at the same location and 
pointing in the same direction as your line of sight. Viewing the cube 
with just your line of sight as the light source, you see no shadows 
since they are hidden from your view, behind the object. 

Now move the light source behind the cube, opposite your line of sight 
(something like watching an eclipse). You are in the cube's shadow, 
out of direct view of the light source. 

Let's take shadowing one step further. Imagine watching the cube from 
sunup to sundown. The shadows change in size, direction and intensity 
as the sun moves in the sky throughout the day. 



2.2.3 Reflection 



An object reflects some light rays and absorbs others, depending on the 
color and reflectivity of the object. The reflected rays enter your eye, 
giving you a mental image of the object's shape, color and texture. 

Let's try to picture this using the computer's visual rays. If the visual 
rays encounter a reflecting surface, they convey the reflection's color, 
brightness and degree of reflection. Then the visual rays travel onto an 
object that lies in the direction of the reflection. From that the object's 
color, brightness and reflection are established. 

This process repeats until the visual rays encounter a non-reflecting 
surface, a dull surface, or no surface at all. Then the visual rays create a 



2. The Basics of Ray Tracing 



Amiga 3D Graphic Programming 



single color, brightness and reflectivity and display this data on the 
screen. The programming examples shown later explain the 
relationship between individual values and the final value. 



2.2.4 



Transparency 



Figure 2.2 



Transparency means that light or visual rays pass through the surface 
instead of reflecting. If your visual rays strike a transparent surface, 
they continue through this surface in the direction they were going 
before encountering this surface (Figure 2.2). Light rays divide (reflect 
and pass through) when a surface is transparent and reflective. However, 
a computer's visual rays cannot pass through a surface and be reflected 
at the same time, so a recursive algorithm must divide the visual rays. 



Normal surface 



A7 



Transparent 



2"^ 



Reflecting 



-A 7 



Reflecting and transparent 



2^ 



2.2.5 



Limitations 



The algorithms developed here can be modified to simulate colors, 
shadows and reflections. There are limitations, however. First, since 
you are working with visual rays instead of true light rays, you cannot 
simulate the light source actually reflecting in a mirror image. Also, 
graphics created by the algorithms have none of the effects caused by 
ambient, indirect or refracted light 

Another limitation: Real light rays comprise all of the colors of the 
visible spectrum, and not just a single color. An object reflects some of 
this spectrum and absorbs the rest. Computer simulations require a 
light source of predetermined color, not the entire spectrum. 



10 



Abacus 23 Presentation in the Computer 



2.3 Presentation in the Computer 



A computer must have the outside world described to it mathematically 
before it can generate 3D graphics. Fairly simple three dimensional 
geometrical formulas let you define lines, planes and circles (see 
Chapter 7 for brief descriptions of the math used). 

Planes The plane is the basic geometric object, described by the following 

equation: 

r + rl + u*r2 = v*r3 

r, rl, r2 and r3 are vectors and u and v are scalars (representing one 
dimension, magnitude without direction), rl is any point that lies on a 
plane. The plane passes through points r2 and r3. r2 and r3 must be 
linearly (one dimensionally) independent of one another. This allows 
the insertion of all possible values for u and v, supplying all allowable 
points that lie on the plane: 




Figure 2.3 

The plane has one disadvantage: It is infinite. This is fine for making a 
background, but you can't define a cube based on planes. Limit the 
definable area for u and v (e.g., [0,1], making u and v greater than zero 
and less than 1). This keeps the size within a specific range. 

Parallelograms If you allow all values of the limited u and v, the points create a 
parallelogram (Figure 2.4). A rectangle results if r2 and r3 are 
perpendicular to each other. Making r2 to r3 perpendicular and equal 
in length creates a square. And joining six squares of equal size together 
creates a cube: 



11 



2. The Basics of Ray Tracing 



Amiga 3D Graphic Programming 



Figure 2.4 



I Parallelogram I 
(u=0, v=l) (u=l, v=l) 

\ / 



(u=0, v=0) 3 




(u=l, v=0) 



r = r + u*r + v* r 

12 3 

with: 0<=u<=l and 0<=v<=l 




Our algorithm divides any body into triangles, so we need triangles in 
the basic figures. This requires a coordinate system and the equation: 

y = -x + 1 

The surface resulting from intersecting the base line and both axes 
looks very similar to a triangle. If you rearrange the formula, you get x 
+ y =l. But where do x and y come from? 

The coordinate system's axes look like vectors at the end (see Chapter 7 
for a description of vectors). Let the x axis be vector r2 and the the y 
axis be vector r3. Now replace x in the formula with u, and y with v. 
Because you want a triangular surface and not only an outline, replace 
the equal sign with a "<=". The result: 

U + V <= 1 

When u and v are both positive values, an infinite surface occurs. You 
make these a limitation for your plane. Insert all allowed values for u 
and v in the plane equation and all of the points lie inside of the trian- 
gle, which has r2 and r3 as two of the sides. 



[Triangle | 




X-axis 1 



Figure 2.5 



r = r + u*r + v*r 

1 2 3 

L with: u>=0 and u+v<=l j 



You can now display any number of rectangular objects using triangles 
and parallelograms. If you create an object from many smaller triangles, 



12 



Abacus 



23 Presentation in the Computer 



Circles 



you have all the basic objects that you might ever need. Some 
disadvantages: Complicated objects require an enormous number of 
triangles, which take up a great deal of memory. Computer memory 
can expand only so far, so we must make some compromises about 
defining basic objects. 

To describe the definition of a circle, we need to talk a bit more about 
how a circle appears in a plane. Remember the general circle formula: 



x2 



y2 



rd2 



Figure 2.6 



rd equals the radius. The formula is simpler for the unit circle: x2 + 
y2 = 1. This is because the unit circle has a radius of 1. The same 
thing is true of our triangle: r2 is the unit vector of the x axis, r3 is 
the unit vector of the y axis, u is x and v is y (never substitute x for 
u instead). The formula now becomes: 

u2 + v2 <= 1 

This time you cannot assume that u and v are positive, even though 
the parallelogram equation required it. Insert all allowable values for u 
and v, and you get a circular object: 




r + u*r + v* 

1 2 

with:u A 2 + v A 2 <= 1 



r2 and r3 should be chosen so that they are perpendicular to each 
other. If r2 and r3 are unequal lengths, you get an ellipse. Having 
direct access to circles saves memory, since you don't have to try 
generating a circular object from small triangles. 

We'll want to create three dimensional circle types later, so we'll need 
circular rings and circle sections (the latter can be used for pie charts). 
These are both obtained from circular surfaces. Rings require the 
lengths of the vectors (u,v) from the circle ring: 



1 = u2 



v2 



This means that 1 must lie in correct intervals between two values. 
This interval value controls the thickness of the circle ring. 

You must do a bit more for the circle section. For the length 1 you 
must also compute the angle w that lies between (u,v) and the r2 axis. 



13 



2. The Basics of Ray Tracing 



Amiga 3D Graphic Programming 



This requires figuring out the polar coordinates. Polar coordinates 
correspond in the 3D computer model to rotation in the real world. 
Compute the polar coordinates from (u,v). You must limit w, just as 
you had to limit 1 for the circle ring. 



Figure 2.7 




To conclude, you also limit w and 1. The resulting figure is a circular 
arc. 



Spheres 



Now we have enough of the basic math to create a sphere. You need to 
know whether or not all possible objects can be broken down into 
triangles. The answer is yes. To create a plain circle out of triangles so 
small that the triangles can no longer be seen as triangles, you need 
about 50 to 100 triangles. You'd need approximately 5000 to 20000 
triangles to create a sphere. A true sphere always has a completely 
round surface, and no corners and edges are visible. The general equation 
for spheres is as follows: 



(r 



rl) 2 



rd2 



rl is the midpoint of the sphere and rd is the radius. We will leave 
this discussion at the sphere and not try to master any new objects. 

Wait. How would you define cylinders, cones and ellipsoids? These 
objects are more difficult to create than the basic objects, but they are 
created using the basic objects described above. 

Until now you have formed additional objects by placing restrictions on 
already existing objects. This is impossible with the sphere because 
there are no other parameters besides the midpoint and radius. Now 
we'll define a three dimensional space for two dimensional objects: 

r = rl + u*r2 + v*r3 + w*r4 

r, rl, r2, r3, and r4 are vectors and u,v and w are scalars. In 
addition, r2, r3 and r4 should be perpendicular to each other. r2, r3 
and r4 may not be co-planar, otherwise they would only form one 
plane. Keep u, v and w unrestricted so that every point in your 
computer universe is a point in your room. 



14 



Abacus 



2 3 Presentation in the Computer 



Figure 2.8 



Now let's try to create a cylinder. Place the ground surface of the body 
on the plane that runs through r2 and r3. Because the ground surface 
of a cylinder is a circle, you can give it the limitation: 



u2 + v2 = 1 



This time there is no inequality because you don't want a filled 
cylinder. Limit w to values between and 1 to keep your cylinder at a 
definite length: 



u2 + v2 = 1 and 0<=w<=l 



l s P ace l yJL / 



|Cylinder| 



(r = r i + u*r 2 + v* r 3 + w*r 4 } 






|Ellipsoid| 



Ellipsoid 



The cylinder is complete. You can give it a further limitation as you 
did to the circular surfaces: Assign an angle interval so that you get a 
cylinder section. Because the procedure is identical to the circular 
surface, specify additional limitations and it becomes a cone. 

The bottom surface of the cone is a circle, so you already know some 
of the restrictions. How do you show that the sides of a cone run 
together to a point? A cone split vertically down the middle reminds us 
of a triangle. The limitation for a triangle is x+y=l. y equals w in this 
case and is also the parameter of the vector that rises to the point of the 
cone, x is the vector that points to a point at the base of the cone: 

x+SQR(u2 + v2) 

While you didn't need the square sign up until now (because the radius 
was one and SQR(1)=1), you must take it use it here to get a result 
similar to a cone. So you get: 

SQR(u2 + v2) + w = 1 

Here you can create a cone section as you did for the circle and cylinder 
by establishing an angle interval or a truncated cone as you restrict w. 

The last basic object is the ellipsoid. You may wonder why you need 
an ellipsoid if you already have a sphere. Unlike the sphere, the 
ellipsoid can have any ellipse form, not just circular. The base surface 



15 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



is a circle, but so is the vertical cross-section. The limitations are 
similar to those for the cone, but this time a different equation is 
needed: 

u2 + v2 + w2 = 1 . 

Make r2, r3 and r4 the same size to get a sphere. Now the second 
advantage of an ellipsoid: You can add limitations to create an ellipsoid 
section. This can look like an apple or melon slice. It is possible to 
limit the parameters to an interval; you can think about the results of 
this on your own. Cone and ellipsoid sections do not appear in the 
routines developed later in this chapter — you'll have to work these out 
on your own. 



2.3.1 Data Structure 



We must establish a data structure for the parameters of the objects to 
be displayed by our program. Because we defined the algorithm in 
BASIC, we used a multidimensional array named K() (see the 
Appendices for the complete program listings). We need four vectors 
for each element of K. These vectors contain information about the 
object type, the material constants and the restrictions. We came up 
with K(MaxNumber,5,2). MaxNumber is the maximum number of 
objects that can be placed in the computer's environment. The elements 
of K are assigned the following parameters: 

K(n,0,0): n = Type of object. This element checks if the n object is 
handled as a plane, a sphere or other object. The following values 
correspond to the following basic objects: 



Plane, infinite 
Triangle 
Parallelogram 
Circle surface 
Circle section 
Circle arc 



10: Sphere 



20: 
21 

22: 
24 



Cylinder 
Cylinder section 
Cone 
Ellipsoid 



As you can see, not all of the above restrictions are built into the data 
structure. While K(n,0,l) is reserved for future use, K(n,0,2) contains 
the index of the materials used to create the object. Instead of placing 



16 



Abacus 23 Presentation in the Computer 



all material constants into array K, the elements are placed in their own 
array called Mat. The array K(n,0,2) specifies the number of elements 
in Mat, which contains the material constant for the nth object. This 
means you can now assign the same material constant to multiple 
objects. 

Note: Some later references to the K() array include periods in parentheses. 

These periods represent allowed values. For example, K(n,l,.) also 
refers to K(n,l,0), K(n,l,l), K(n,l,2), etc. 

K(n,l,.) always contains the vector rl. K(n,l,0) is the x component, 
K(n,l,l) is the y component, and K(n,l,2) is the z component of the 
vector, which also works in conjunction with other vectors. K(n,2,.) 
through K(n,4, . ) contain the vectors needed for their respective objects 
(vectors r2 through r4). For example, K(n,2,0) contains the radius of 
the sphere. 

The restrictions overlap with vector r4, but that restriction does not 
apply to cylinders, cones and ellipsoids. K(n,4,0) is the lower limit and 
K(n,4,l) is the upper limit of the circle arc in the equation SQR(u2 + 
v2). The values must be between zero and one. K(n,5,l) contains the 
start angle for circle sections, circle arcs and cylinder sections. K(n,5,l) 
specifies the end angle in degrees. When they are placed all together 
they look like this: 

K(n,0, 0) = type 

K(n,0,l) = reserved 

K(n,0,2) = index for material constants 

K(n, 1, .) = rl 

K(n,2,0) = radius for sphere or 
K(n, 2, .) = r2 

K(n,3, .) = r3 

K(n,4,.) = r4 or if circle arc 
K(n,4,0) = lower limit (inner radius) 
K(n,4,l) = upper limit (outer radius) 

For circle section, circle arc or cylinder segment: 

K(n,5,0) = start angle 
K(n,5,l) = end angle 

The data structure for the material constants is very easy. The field is 
dimensioned with Mat(Numbermat,6). The color of the material is 
established first: Mat(n,0) contains the red section, Mat(n,l) the green 
section and Mat(n,2) the blue section. No ambient light exists in our 
computer world, and this would make all shadows almost solid black. 
To alleviate this, we define a shade brightness for every material which 
defines the brightness of the material in the shadows. Assign this 



17 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



material a small value — a larger value makes it difficult to differentiate 
between shadows and where light actually falls. 

Mat(n,4) contains the reflection factor. When this equals zero, the 
surface of the material is dull. When Mat(n,4) equals one, the surface 
appears as a highly polished mirror. Mat(n,5) contains the 
transparency factor, but our program doesn't use it, and Mat(n,6) is 
reserved for additions to the program. The data structure for Mat is as 
follows: 

Initial material brightness! 

mat(n,0) = Red material brightness! 

mat(n,l) = Green material brightness! 

mat(n,2) = Blue material brightness! 

mat(n,3) = Factor for unlit/shadow! 

mat(n,4) = Factor for mirroring! 

mat(n,5) = Factor for transparency (not implemented)! 

mat(n,6) = reserved! 

All values must be between zero and one. 

Here's an example. When you want to know the reflection factor of 
object number 47, get the material index: 

PRINT K(47, 0,2) 

Imagine that you get the value 12. Now you can specify the reflection 
factor with: 

PRINT Mat(12,4) 

The abbreviated entry for this data is as follows: 

PRINT Mat (K(47, 0,2) , 4) 

This syntax is the form used by the routines presented in the program. 



18 



Abacus 



2.4 Simulating Perception 



2.4 



Simulating Perception 



The data structure assembles an artificial reality in our computer, and 
now we must bring it to the screen. First we must determine the point 
of view from which we want to see the graphic. 

In your simulation model you sent out visual rays from every point on 
the screen in the direction of the lens. We will proceed with this 
method in our algorithm. We send visual rays from the projection point 
P in the direction of the screen, and assign one visual ray to each screen 
pixel. We must now determine the position of the screen. The main 
point H performs this task. H lies in the exact center of the screen. The 
vector p-H is the normal vector on your screen; it lies perpendicular 
from the projection point to the middle of the screen. The distance 
between P and H is called DPH. 



J Projection point P ^ Main point H | 
| Screen| 




Figure 2.9 



Note: 



Because you must compute the picture using points (pixels), the 
algorithm is simple: Provide the three dimensional coordinate for every 
pixel you have to compute. Then send a visual ray from the projection 
point in the direction of this pixel and determine whether you see 
something. Our routine determines what we see and don't see, 
especially the color of the point. Once the program decides, the point is 
displayed on the screen. The entire procedure is in the following 
subroutine taken from the tracer program listed in the appendices. 

The example programs that follow contain some BASIC lines that 
must be entered on one line in AmigaBASIC even though they appear 
on two lines in this book. Fitting some formatted program listings in 
this book has caused some long BASIC lines to be split into two lines. 
End of paragraph characters fl]) in these program texts show the actual 



19 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



end of a line of BASIC code. These characters indicate when the 
<Return> key should be pressed in the BASIC editor. 

Shadows :1 

1 Initialization^ 

Status$ = " Status: Shadows "+CHR$ (0) 1 
CALL SetWindowTitles&(NWBase&,SADD(Status$) ,0)1 
1 

GOSUB DeleteMenul 
1 

Status$ = " Status: Init"+CHR$ (0) 1 
CALL SetWindowTitles&(NWBase&,SADD(Status$) ,0)1 
GOSUB InitShadowsl 
1 

Status$ = " Status: InitMinMax"+CHR$ (0) 1 
CALL SetWindowTitlesS (NWBase&, SADD (Status$) ,0)1 
GOSUB InitMinMaxf 
1 

Status$ = " Status: InitMinMaxLq"+CHR$ (0) 1 
CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0) SI 
GOSUB InitMinmaxLql 
1 

CALL Scronl 
1 

Status$ = " Status: Shadows"+CHR$ (0) 1 
CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0)1 
1 

XAOff = (BoxW% AND 1)*.51 
YAOff = (BoxH% AND 1)*.51 
1 

' Offsets to guarantee correct point sizel 
IF XAOff = .5 THEN1 

XBOff = .51 
ELSE1 

XBOff = 11 
END IF1 
IF YAOff - .5 THEN1 

YBOff = .51 
ELSE1 

YBOff = 11 
END IF1 
1 

Body%-01 
1 

FOR yb%=YStart%+BoxH%/2 TO Yend%+BoxH%/2 STEP BoxH%1 
FOR xb%=XStart%+BoxW%/2 TO XEnd%+BoxW%/2 STEP BoxW%1 
CALL ReProjection(Rx,Ry,Rz,0! ,FN Xresc (xb%) , FN 
Yresc(yb%))1 
1 

Rx = Rx-Pxl 
Ry = Ry-Pyl 
Rz = Rz-Pzl 
1 

StackPtr% =-11 
1 

Pxl = Pxl 

Pyl = Pyl 

Pzl = Pzl 

1 

Original! = Truel 

GOSUB Computepointl 



20 



Abacus 2.4 Simulating Perception 



Px = Pxlfl 
Py = Pylfl 
Pz = Pzlfl 

IF Stack (0,0 )>=0 THEN 'If no Intersect point => -1$ 
Bright . r=Stack (0,0) *Qh . r<jl 
Bright . g=Stack ( , 1 ) *Qh . gfl 
Bright . b=Stack (0,2)*Qh.bf 

CALL OSSetPoint& (CLNG (xb%-BoxW%/2+XAOf f ) , 
CLNG (yb%-BoxH%/2+YAOf f ) , 
CLNG (xb%+BoxW%/2-XBOf f ) , 
CLNG (yb%+BoxH%/2-YBOf f ) , 
CLNG(1024*Bright.r) , 
CLNG(1024*Bright.g) , 
CLNG(1024*Bright.b) ) f 
END IFfl 
NEXT xb%! 
1 

IF INKEY$ <> "" THEN1 

IF yb% < Yend%+BoxH%/2 THENl 

CALL Scrofffl 

a$="Next line: "+STR$ (yb%+BoxH%) fl 

CALL PrintIt(a$,130,Falr.e)fl 

CALL DialogBox ("Continue", 0, True,xla%, yla%,x2a%, 
y2a%, False) f 

CALL DialogBox ("Stop", 2, False, xlb%, ylb%, x2b%, 
y2b%, False) f 

CALL DoDialog(n%,0,xla%,yla%,x2a%,y2a%, -1,-1, -1, - 
1, xlb%, ylb%, x2b%, y2b%) 1 

CLSSI 

IF n% = THEN1 

CALL Scronl 
ELSEl 
GOTO ShadowEndel 
END IFfl 
END IF ^ 
END IF! 
NEXT yb%SI 

ShadowEnde : SI 

CALL ScroffH 
CLS<I 

GOSUB MakeMenu f 
RETURN! 

The above routine starts by initializing an open window, shadowing 
and the area to be shadowed. The important section begins with the two 
FOR-TO loops which check all of the screen points. BoxW% and 
BoxH% specify the width and height of the screen points in pixels 
(usually a value of 1). The loop calculates the three dimensional 
coordinates from the two dimensional screen coordinates. 

Re projection works like a return function to Projection, 
which projects three dimensional coordinates on the screen. The 



21 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



functions Xresc and Yresc help configure later enlargements of the 
screen area. Next, the vector runnig from P in the direction of the 
screen points is computed (Rx,Ry,Rz). Then p is saved and the 
ComputePoint function is called, which computes the color of the 
screen points. The result of the computation is stored in the zero 
element of St ackO- The red element of the color passes Stack(0, 0), 
the green element to Stack(0,l), and the blue element to 
St ack(0 , 2). The stack is there mainly for reflections. 

When Stack(0,0) is negative, this screen point contains nothing, and 
we leave the background as it was. Otherwise the program considers the 
color of the light source (Qh.r = red element, Qh.g = green element, 
Qh.b = blue element) and displays the point with theOSSetPoint& 
routine. This presents a problem. This routine displays a rectangle on 
the screen and tries to arrive at a color as close as possible to the desired 
color. 

After a line is computed, the routine checks to see if the user has 
pressed the spacebar. If so, the program asks if the user wants to stop 
the calculation. The Scron/Scroff calls only bring the graphic 
screen to the foreground or place it in the background (the DialogBox 
function is listed later in this book). 



2.4.1 What Do You See? 



Let's take a closer look at what happens on the screen. 

We defined the basic objects using mathematical equations to make it 
easy to calculate points of intersection with a line. The line described 
here is the visual ray. This visual ray begins at projection point P and 
runs through the actual screen point. A line equation can also be 
written in point — direction form: 

r = rl + l*r2 

r, rl, and r2 are vectors and 1 is a scalar (see Figure 2.3). The point 
rl that runs through the line, is the equivalent of your projection 
point. r2 specifies the direction of the line which is equivalent to your 
vector R (Rx,Ry,Rz) calculated above. To provide an intersection with 
the plane, you set the line and plane equations equal to each other so 
that you can figure out parameters 1, u and v. You can obtain the 
intersection point by inserting 1 in the equation and calculating this. 
The following SUB program contains the intersection point calculation: 

SUB IntersectpointPlane(n%,Px,Py,Pz,Rx,Ry,Rz,l) STATIC^ 
SHARED Help(),K() 1 

1 => 1 = exact parameter*! 

D=Ry*Help (n%, 4) -Rx*Help (n%, 3) -Rz*Help (n%, 5) i 



22 



Abacus 2.4 Simulating Perception 



IF DOO THEN! 

l=((Px-K(n%,l,0))*Help(n%,3)-(Py-K(n%,l,l) ) *Help (n%, 4) + (Pz- 
K (n%, 1, 2) ) *Help (n%, 5) ) /D5 
ELSE! 

l=-lf 
END IF! 
END SUB! 

You assign the end point of the line (Px,Py,Pz) and the direction 
vector (Rx,Ry,Rz). In addition, n% establishes which plane should be 
used to calculate the intersection point. The line parameter 1 is returned 
from the subroutine. When no intersection point exists, 1 = -1 is 
returned. 1 can be negative. This places the intersection point behind 
you (i.e., you can't see the intersection point). You should only be 
interested for now in the things that you can see. 

You can read how to solve the equation system in the mathematical 
basics chapter (Chapter 7). You must first calculate the denominator 
determinant. This looks like the following: 

Line:r = r + l*r , Plane:r = r + u*r + v*r 

PR' 1 23 

Intersect point: l*r - u*r - v*r = (r - r ) 

^ R 2 3 1 P 



Figure 2.10 



Rx (K(n,2,0) K(n,3,0)| 

Ry (K(n,2,l) K(n, 3, 1) I Naming determinant 

Rz (K(n,2,2) K(n,3,2)| 



D 

v 



i 

IK(n,l,0)-Px K(n,2,0) K(n,3,0) I 
K(n / 1 / 1)-Py K(n,2,l) K(n,3,l) I 
K(n,l,2)-Pz K(n,2,2) K(n,3,2) | 

IRx K(n,l,0)-Px K(n,3,0) 1 

Ry K(n / 1 / 1)-Py K(n,3,l) I 

Rz K(n,l,2)-Pz K(n,3,2) | 

IRx K(n,2,0)-Px K(n,l,0)-Px| 
Ry K(n,2,l)-Py K(n,l,l)-Py I 
Rz K(n,2,2)-Pz K(n,l,2)-Pz | 



D T = 



D 

U 



G 


d ) 




u 


d J 




k 


D 1 

_ v 



Only one line is unknown in this determinant — the direction of the 
line. You must solve the determinant for this line. The 2x2 sub- 
determinant contains all of the values that do not change. Here you 
calculate these values and store them in the array Help(). It looks like 
this: 

Help(n%,3) = K (n%, 2, 1) *K (n%, 3, 2) -K (n%, 3, 1) *K (n%, 2 , 2) 
Help(n%,4) = K(n%,2,0)*K(n%,3,2)-K(n%,3,0)*K(n%,2,2) 
Help(n%,5) - K(n%, 2, 0) *K (n%, 3, 1) -K (n%, 3, 0) *K (n%, 2 , 1) 

No intersection point exists if the denominator is zero. This means that 
the plane and the line are parallel. Instead, 1 is directly calculated and 
returned to the called program. 

Before you calculate the intersection point for other basic objects, a few 
words about general procedure: For every object in your computer 
world, test for the intersection point with the visual ray. This way we 



2 3 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



find how many objects are next to it; we also search for an object with 
a minimal 1. When we find this, we also get the number of objects 
that can be seen in the current screen. 

Now on to the intersection points of other basic objects. The preceding 
subprogram is identical to that of the triangle except that the additional 
parameters u and v must be computed and then tested to see if the 
restrictions for the triangle are enough: 

SUB IntersectpointTriangle(n%,Px,Py,Pz,Rx,Ry,Rz,l,a,b) STATIC^ 
SHARED Help(),K()f 

' => 1 = exact parameter, a,b = area parameter^ 
D=Ry*Help (n%, 4) -Rx*Help (n%, 3) -Rz*Help (n%, 5) f 
IF DOO THENi 

1= ( (Px-K (n%, 1, 0) ) *Help (n%, 3) - (Py-K (n%, 1,1)) *Help (n%, 4) + (Pz- 
K(n%,l,2))*Help(n%,5))/Dfl 
IF 1>0 THENf 

a=FN Det (Px-K(n%, 1, 0) ,K(n%, 3, 0) , -Rx,Py- 
K(n%,l,l),K(n%,3,l),-Ry,Pz-K(n%,l,2),K(n%,3,2),-Rz)/DS[ 

b=FN Det (K(n%,2,0) ,Px-K(n%,l,0) , -Rx,K (n%, 2, 1) , Py- 
K(n%,l,l),-Ry,K(n%,2,2),Pz-K(n%,l,2),-Rz)/Dfl 

IF a<0 OR b<0 OR a>l OR b>l OR a+b>l THEN5 

l=-lf 
END IFl 
END IFfl 
ELSEf 

1=-11 
END IF1 
END SUM 

The Det function calculates only the value of a determinant. The 
intersection point calculation for the parallelogram, circle, circle 
section, and circle arc are similar — the only difference being the 
restrictions. The name of the SUB program appears in parentheses (see 
the complete listing in the appendices): 

Parallelogram (IntersectpointRectangle) : 
IF a<0 OR b<0 OR a>l OR b>l THEN 

1 = -1 
END IF 

CircleSurface (IntersectpointCircle: 
IF a*a+b*b>l THEN 

1 = -1 
END IF 

CircleSection (IntersectpointCircleSector) : 
IF a*a+b*b< = 1 THEN 

CALL Angellnterval(l / n% / a,b) 
ELSE 

1 = -1 
END IF 

Circlearc (IntersectpointCircleRing) : 
d = SQR(a*a+b*b) 

IF (d> = K(n%,4,0)) AND (d< = K(n%,4,l)) THEN 
CALL AnglelntervalUjnl^b) 

ELSE 
1 = -1 



24 



Abacus 2.4 Simulating Perception 



END IF 

Anglelnterval tests to see if the intersection point lies inside of 
the defined angle interval: 

SUB Anglelntervall(l,n%,a,b) STATIC^ 
SHARED Pi,Pm2,Pd2,K()f 
IF a=0 THENfl 

D=Pd2*SGN(b)fl 
ELSEfl 

D=ATN(b/a)fl 
IF a<0 THENfl 

D = D+Pi^ 
END IFfl 
END IF$ 
IF D<0 THENfl 
D = D+Pm2fl 
END IFf 

And now check if this lies in the defined interval: 

IF D<K(n%,5,0) OR D>K(n%,5,l) THENf 

l=-lfl 
END IFfl 
END SUM 

Pi is the circle value 3.141592, Pm2 = 2*Pi and Pd2 = pi/2. Here 
we see in detail how you can calculate the angle. 

For the sphere, insert the line equation in the sphere equation and 
calculate this. We get a quadratic equation system that can be solved 
using the standard procedure. A problem: We can only compute a 
maximum of two intersection points. We must compute the parameter 
1 for both. Then we choose where the next one lies. 

SUB IntersectpointSphere(n%,Px,Py, Pz,Rx, Ry,Rz, 1) STATIC^ 
SHARED Help () ,K(), Threshold^ 
1 => 1 = exact parameter^ 
D=Rx*Rx+Ry*Ry+Rz*Rz ( II 

p= (Rx* (Px-K (n%, 1,0)) +Ry* (Py-K (n%, 1 , 1 ) ) +Rz* (Pz-K (n%, 1, 2) ) ) /Df 
q= ( (Px-K (n%, 1, 0) ) A 2+ (Py-K (n%, 1, 1) ) A 2+ (Pz-K (n%, 1, 2) ) A 2- 
K(n%,2,0)*K(n%,2,0) ) /Df 
D=p*p-qfl 
IF D>=0 THENfl 
l=-p+SQR(D)1 
Ll=-p-SQR(D)fl 
IF (LK1) AND (Ll>Threshold) THEN$ 

SWAP 1,LH 
END IFf 
ELSEf 

i=-m 

END IFf 
END SUM 

This time we test to see if LI is greater than Threshold (set at 
0.0001), instead of whether it is greater than zero. This Threshold is 
used for shades and reflection. Because they work with the same 
routine, the test must already exist. 



25 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



Until now the routine to calculate the intersection point was straight- 
forward, to a certain extent. Now we come to the cylinder and its uses. 

There are three unknowns in the cylinder equation and one in the line 
equation, so setting them equal will not solve anything. To solve this 
we would have to solve a 4x4 determinant. Let's try something else. 

A coordinate system is set up by the three direction vectors. When we 
convert the coordinates from P and R into this coordinate system (basis 
transformation), we can calculate the intersection point of the line with 
the cylinder. The cylinder equation is reduced to: 

u A 2 + v A 2 = 1 and 0< = w< = 1 

( u , v , w ) should be the intersection point with the line. The line 
equation, split into three coordinate equations, reads: 

u = Pxt + l*xt 
v = Pyt + l*yt 
w = Pzt + l*zt 

(Pxt,Pyt,Pzt) is the transformed projection point and (xt,yt, 
zt) is the transformed direction vector. When we insert these in the 
cylinder equation, we get: 

(Pxt + l*xt)~2 + (Pyt + l*yt) A 2 =1 
< = (pzt + l*zt) < = 1 

Now 7 there is only one unknown and this can be calculated after some 
rearranging: 

1*2* (xt A 2+yt A 2) + I*(2*Pxt*xt+2*Pyt*yt) + (Pxt A 2+Pyt' s 2-l) = 

The further calculating of this equation is taken care of by the 
following SUB program: 

SUB IntersectpointCylinder (n%, Px,Py, Pz,Rx,Ry, Rz, 1, a,b, c,0 
riginal ! ) STATIC! 
SHARED Threshold! 

1 => l=exact parameter, a,b,c = transform Intersect point 
coordinates! 

CALL 
Basistrans(n%,Pxt,Pyt,Pzt,Xt,Yt,Zt,Px,Py,Pz,Rx,Ry,Rz, Original!)! 
D=Xt*Xt+Yt*Yt! 
IF DOO THEN! 

p=(Pxt*Xt+Pyt*Yt)/D! 
q- (Pxt*Pxt+Pyt*Pyt-l) /D! 
D=p*p-q! 
IF D>=0 THEN! 
1=-P+SQR(D)! 
Ll=-p-SQR(D)1 
c=Pzt+l*Zt! 
D=Pzt+Ll*Zt! 

'two solutions : l,c and Ll,d. Which is right? 
IF LK1 AND Ll>Threshold AND D>=0 AND D<=1 THEN! 
SWAP 1,L1! 



26 



Abacus 2.4 Simulating Perception 



SWAP c f Df 
END IFf 

'1 and c contain the correct solution parameter: 
IF c<0 OR Ol THENSI 

l=-lfl 
ELSEfl 

a=Pxt+l*Xt<II 
b=Pyt+l*Ytfl 
END IFfl 
ELSEfl 

1=-H 
END IF1 
ELSEfl 

1=-15 
END IFfl 
END SIM 

Here, like the sphere, two solutions are possible, and they both must 
be calculated. From these the intersection point is chosen, c and d 
satisfy both solutions for w and must be between zero and one. When 
an intersection point exists, a and b (the solutions for u and v) are 
computed. 

This time an additional parameter comes in the parameter assignment: 
Original ! This is needed for BasisTrans. BasisTrans 
converts the vectors P and R in the coordinate system of the cylinder: 

SUB Basistrans(n%,Pxt,Pyt,Pzt,Xt,Yt, Zt,Px,Py, Pz,Rx, Ry,Rz, 
Original!) STATIC^ 
SHARED HelpO ,K()fl 

1 Transform (px,py,zy) => (pxt,pyt,pzt) , (rx,ry,rz) => 
(xt,yt,zt)fl 
f 

IF Original ! = True THEN1 
Pxt=Help(n%,10)fl 
Pyt=Help(n%,ll)fl 
Pzt=Help(n%,12)$ 
ELSEfl 

Pxt= (Px-K(n%,l, 0) ) *Help (n%, 13) - (Py- 
K(n%, 1, 1) ) *Help (n%, 14) + (Pz-K (n%, 1,2)) *Help (n%, 15) f 

Pyt= (Px-K (n%, 1 , 0) ) *Help (n%, 16) - (Py- 
K(n%,l,l) )*Help(n%,17) + (Pz-K(n%,l,2) ) *Help (n%, 18) f 

Pzt=(Px-K(n%,l,0))*Help(n%,19) - (Py- 
K(n%,l,l) )*Help(n%,20) + (Pz-K(n%,l,2) ) *Help (n%, 21) f 
END IF<5 

Xt=(Px+Rx-K(n%,l,0) ) *Help(n%,13)-(Py-:-Ry- 
K (n%, 1, 1) ) *Help (n%, 14) + (Pz+Rz-K(n%, 1, 2) ) *Help (n%, 15) -Pxtfl 

Yt= (Px+Rx-K(n%, 1, 0) ) *Help(n%, 16) - (Py+Ry- 
K (n%, 1, 1) ) *Help (n%, 17) + (Pz+Rz-K (n%, 1, 2) ) *Help (n%, 18) -Pytfl 

Zt= (Px+Rx-K(n%, 1,0)) *Help (n%, 19) - (Py+Ry- 
K(n%,l,l) )*Help(n%,20) + (Pz+Rz-K(n%,l,2) ) *Help (n%, 21) -Pztfl 
END SUB$ 

The beauty is that the transformed coordinates of the projection point 
do not change during the entire calculation. We can calculate these 
beforehand and save them in our Help array. Because the intersection 
point routine is also used for reflection and shade calculation another 
point is inserted instead of the projection point (Px,Py,Pz). This is 



27 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



why we must write an IF-THEN-ELSE construct. When Original ! 
is true, (Px,Py,Pz) contains the coordinates of the original projection 
point. 

The basis transformation is the solution of an equation system with 
three unknowns. The transformed point is simply inserted in the body 
equation, which looks like the following for P: 

P = rl + u*r2 + v*r3 + w*r4 

or solved in the coordinate equations: 

Px = rlx + u*r2x + v*r3x + w*r4x 
Py = rly + u*r2y + v*r3y + w*r4y 
Pz = rlz + u*r2z + v*r3z + w*r4z 

The equations must now be solved and the parameters u, v and w must 
be computed. Since the denominator determinant is one, this time we 
don't have to do extra calculating. When computing the determinant we 
can use the fact that only one column is unknown while the two others 
are constant. We can calculate these beforehand and store them in 
Help. 

With this, the intersection point of a line with a cylinder can be calcu- 
lated. We must create a check of the angle interval of parameters a and 
b for a cylinder section: 

(IntersectpointCylinderSegm) 
1- -p+SQR(D) 
LI - -p-SQR(D) 
c = Pzt+l*Zt 
CI = Pzt+L±*Zt 

'Test for solution c, 1 angle interval 

IF c> = AND c< = 1 THEN 

CALL Anglelnterval (1, n%,Pxt+l*Xt, Pyt + l*Yt) 
ELSE 

1 = -1 
END IF 

'Now for the second solution 

IF Cl> = and Cl<= 1 THEN 

CALL Anglelnterval (11, n%, Pxt+Ll*Xt , Pyt+ll*yt ) 
ELSE 

LI = -1 
END IF 

'If the second solution is better: Exchange 

IF (K-.5) OR (LK1 AND Ll>Threshold) THEN 

SWAP 1,11 

SWAP c,Cl 
END IF 

'Correct solution in c, 1 



28 



Abacus 2.4 Simulating Perception 



a = Pxt+l*Xt 
b = Pyt+l*Yt 

The subprograms for cones and ellipsoids don't have any special differ- 
ences from the one for the cylinder. The procedure is identical. The 
equations look a little different because the restrictions have a different 
form: 

Cone (IntersectpointCone) : 
d = Xt*Xt+Yt*Yt-Zt*Zt 
IF d<>0 THEN 

p= (Pxt*Xt+Pyt*Yt+Zt* (1-Pzt) ) /d 

q = (Pxt*Pxt+Pyt*Pyt-(l-Pzt) A 2)/d 

d = p*p-q 



END IF 

Ellipsoid (IntersectpointEllipsoid) : 

d = Xt*Xt+Yt*Yt+Zt*Zt 

IF d<>0 THEN 

p= (Pxt*Xt+Pyt*Yt+Pzt*Zt) /d 

q= (Pxt*Pxt+Pyt*Pyt+Pzt*Pzt-l) /d 

d = p*p-q 



END IF 

These two program sections are found in the SUB programs following 
the BasisTrans call in the complete tracer program (see the 
appendices for the listing). 

We can now determine which objects we see in the picture at point 
bx,by . This is done by converting (bx,by) to three dimensional 
coordinates and testing for the line that goes through p at point R. 
Then we calculate all of the intersection points of this line and all 
bodies and find which is next to us. The equivalent SUB program is 
called WhichBody, because it establishes which body the line 
intersects: 

SUB WhichBody (Kp%, Px,Py,Pz,Rx,Ry, Rz, Original !, Shadown ! ) STATIC! 

SHARED True, False, minmax% () , NumberK, minmaxlq () , 

HelpO ,K() , xb%,yb%,Sx,Sy,Sz,Body%, Ac, Be, Cc, la, Threshold! 

' => Body% = Nr the body under coordinates xb%,yb%, 
S (sx, sy, sz) ^Intersect point, la=intersection lineal 

1 => if Typ>=20: (ac,bc, cc) - transform Intersect point 
coordinates! 
la=-l! 
Body%=0! 
! 

FOR n%=l TO NumberK! 
! 
IF K(n%, 0,0=0 THEN! 

CALL Intersect pointP lane (n%, Px, Py , Pz, Rx, Ry , Rz, 1) ! 
GOTO Wkok! 



29 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



END IF! 

IF K(n%,0,0)=l THEN! 

CALL IntersectpointTriangle(n%,Px,Py,Pz,Rx,Ry,Rz, 1, a,b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=2 THEN! 

CALL IntersectpointRectangle (n%, Px, Py, Pz / Rx / Ry, Rz, 1, a,b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=3 THEN! 

CALL IntersectpointCircle (n%, Px,Py, Pz, Rx,Ry, Rz, 1, a,b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=4 THEN! 

CALL IntersectpointCircleSector (n%, Px, Py, Pz, Rx, Ry, Rz, 1 
,a,b)! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=5 THEN! 

CALL IntersectpointCircleRing(n%,Px,Py,Pz,Rx,Ry,Rz, 1, 
a,b)! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=10 THEN! 

CALL IntersectpointSphere(n%,Px,Py,Pz,Rx,Ry,Rz, 1) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=20 THEN! 

CALL IntersectpointCylinder (n%, Px, Py,Pz, Rx,Ry, Rz, 1, a,b,c, 
Original!)! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=21 THEN! 

CALL Inter sect pointCylinderSegm (n%, Px, Py, Pz, Rx, Ry, Rz, 1 , a, 
b,c, Original!)! 

GOTO Wkok! 
END TF! 
IF K(n%,0,0)=22 THEN! 

CALL IntersectpointCone (n%, Px, Py, Pz, Rx, Ry, Rz, 1, a,b,c, 
Original!)! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=24 THEN! 

CALL IntersectpointEllipsoid(n%,Px,Py,Pz,Rx,Ry,Rz, 1, a, b, c, 
Original!)! 
END IF! 
Wkok:! 
1 Work OK!! 
! 

IF (l>Threshold) AND (la<=0 OR Kla) AND (n%OKp% OR 
K(n%,0,0)>=10) THEN! 

la=l! 

Body%=n%! 

IF K(n%,0,0)>=20 AND Kp%=0 THEN! 
Ac=a! 
Bc=b! 
Cc=c! 

END IF! 
END IF! 
Nxtk:! 
1 Next body! 
NEXT n%! 



30 



Abacus 2.4 Simulating Perception 



31 

IF Body%>0 AND Kp%=0 IHEN<jI 

Sx^Px+la*Rxl 

Sy=Py+la*Ry , 5 

Sz=Pz+la*Rz<i[ 
END IF % 
END SUB<fl 

Original ! is set to true when it is established which object is 
visible at the current screen position. It is false when reflection is in 
effect. Shadown ! becomes false when the shadow is calculated. 

The endpoint of the (visual ray) line is assigned in (Px,Py,Pz) and the 
direction vector in (; x,Ry,Rz). As a result you get the number of the 
body where (Px,Py,Pz) lies next in Body%. Kp% is needed for the 
shadow and is explained in that routine. 



2.4.2 What You Should See 



It's not enough simply to bring the color of the body to the screen. 
That would give us the outline of the body and nothing else. We need 
to see the brightness of the body's surface. 

We already know that a surface shines brighter when light rays strike 
perpendicular to the surface. All we have to do is test for the angle that 
lies between the normal vector on the intersection point and the line 
from the intersection point to the light source. The brightness is at a 
maximum when this angle is zero, and when this angle is greater than 
90 degrees, the point is dark because the light shines on it from 
"below." 



Figure 2.11 




+ 

Project; ion point P 



Intersection 
point S 



We have one simple way of determining whether a point of a surface is 
in the path of the light source. As a measurement for the brightness of 
the surface we take the cosine of the angle. This is convenient, because 



31 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



the cosine for perpendicular light rays (0 degrees) is one and for 
extremely flat light rays (90 degrees) is zero. We just have to multiply 
these by the three color intensities of the surface (red, green, blue) to 
get the correct color tone. The cosine for angles over 90 degrees is 
negative, so a simple test for a negative leading character sees if the 
point lies in the path of the light source. 

In nature, there is no universal function to calculate the brightness of a 
surface. Different material can have different brightness under the same 
light. Because we cannot cover them all here, we use the cosine because 
the cosine of the angle between two vectors can be calculated very 
easily. 

Now we need to find the normal vector. For planes, triangles, 
parallelograms, etc., this remains the same during calculation, so that 
we can compute it before the calculation and store it in Help. The 
normal vector is the product of vectors r2 and r3, which cross the 
plane. The normal vector is easier to compute for the sphere. The 
normal vector is the same as the vector from the midpoint of the sphere 
to the intersection point. 

It is more difficult for cylinders, cones, and ellipsoids. It's not enough 
to compute the normal vector in (r2,r3,r4) and then change it back. 
There are other options. 

The normal vector is parallel to the base surface of the cylinder, so we 
need only consider vectors r2 and r3. The base surface of the cylinder 
is (in the general case) an ellipse, and an equation for this already 
exists: 

(x /N 2 / a ~ 2 ) -f- { y * 2 / b~2) — 1 

Solution for y: 

y = b * SQR(l-(x"2 / a~2) ) 
y - b/a * SQR(a"2 - x"2) 

This equation solves y and gives the slope of the ellipse : 

y' = -b/a * x/SQR(a"2 - x"2) 

When we regard y' as the slope of a line, it is perpendicular to our 
desired normal vector. We obtain the perpendicular by taking the 
negative return value of the slope. The slope of the perpendicular is 
equivalent to ny/nx, also the slope of the normal vector: 

ny/nx - a/b * SQR(a"2 - x A 2)/x 

We split these into an equation for nx and for ny so that ny/nx does 
not change: 

ny = (a*b) *5QR(a~2 - x"2) 



32 



Abacus 2.4 Simulating Perception 



nx = (b"2) *x 

This seems rather arbitrary, but it solves the equation to our advantage. 
Now we insert the original ellipse equation in the formula for ny to 
solve the base, and for ny we get: 

ny - (a*b) * (y*a/b) = > 
ny = (a*2) *y 

Now we have two equations for nx and ny. But the disadvantage is that 
in our cylinder equation we don't have a, b, x, or y. We must now 
determine which parameters each represents, a is the main axis of the 
ellipse which corresponds to the length of vector r2, or Ir2l. b is the 
other axis and corresponds to the length of r3, or Ir3l. x and y are 
coordinates of a point which we call u* r2 and v* r 3, where u and v 
are intersection point parameters. Because our parameter vectors have 
different directions, we can add the equation for nx and ny. The result 
is the normal vector for the cylinder: 

n = |r3r2 * u*r2 + | r2 T2 * v*r3 

Because the quadratic of the length of r2 and r 3 does not change, we 
place these in our Help array, which saves us a lot of time. 

Things look very similar for the cone, except that the normal vector 
arcs in the direction of the cone point. We first create the normal vector 
from the base ellipse. Then we change the length of the normal vector 
so it is exactly athe length of u* r2 + v* r 3. Now we retain the length 
from r 4 to the length of the normal vector, which is exactly the slope 
of the cone surface when we consider a longitudinal section of the cone. 
We get the calculation of the perpendicular from the normal vector on 
this point of the cone surface. n2 is the normal vector on the base 
surface as it was already written above for the cylinder. So: 

nl = n2/ |n2 I * |u*r2 + v*r3 | 

is the normal vector on the base surface with a length ofu*r2+v*r3. 
The direction remains the same. The normal vector on the cone surface 
is given by: 

n = |nl | / |r4 | * r4 + |r4 1/ |nl | * nl 

The derivation of the normal vector for the ellipsoid will not be 
discussed here because of page limitations. However, we can supply the 
equation which provides the solution: 



( |r3T2 + 


Ir4 T2) 


* u*r2 


( Ir2r2 + 


Ir4 I "2) 


* v*r3 


( |r2 1 "2 + 


lr3T2) 


* w*r4 



Now we can test for the brightness of every point of the basic object 
surfaces, once we establish the location of the light source. It would be 
best if we could see the reflection of light on the surface of our object. 



33 



2. The Basics of Ray Tracing 



Amiga 3D Graphic Programming 



We calculate the reflected light rays; the angle between them and the 
visual rays; and the vector from intersection point to projection point. 
When this angle is zero, we are looking directly into the light source, 
and the reflected light is very dark. The larger the angle, the greater the 
reflection of light. 

To obtain the reflected light rays we first compute the distance of light 
source Q from the plane that runs tangential to the surface through 
intersection point S. Now multiply the normal vector n by a factor that 
makes the length the same as the distance from Q to the tangent plane. 
After that test the reflected vector SP is as follow?: 



SP 



(S-Q) + 2*n 



Figure 2.12 



P 
I 



SP 




Instead of the angle, we use the cosine and store it in the variable 
Mirror. So the reflected light level stays low, we increase the result 
by a relatively high power so that the value of Mirror is close to zero 
for small angles. 

Now we can finally put all of the calculations together to get the 
brightness of a point on a surface. We've put them into a SUB program 
named Set Brightness. The brightness is stored in the variable 
Bright and the reflection of the light source is stored in Mirror. 
This SUB program has nothing to do with the color of the body. This 
comes later. 

SUB SetBrightness(n%,Px,Py,Pz, Mirror, Original! ) STATIC! 

SHARED 

HelpO ,K() , Mat () , Ox, Qy, Qz, Ac, Be, Cc, Sx, Sy, Sz,Nx, Ny , Nz , Nl, Spx, Spy, 

Spz, Bright f 

' => Bright=Brightness, SP=Mirror Vector, Mirror=Intensity of 
LQ-Mi r r o rung 5 
1 

IF K(n%,0,0)<=9 THEM 

' Determine Mirror Vektor SPI 
Nx=Help(n%,0)i 
Ny-Heip(n%,l) ( 5 
Nz=Help{n%,2)SI 



34 



Abacus 2.4 Simulating Perception 



IF Original !<>True THEN! 

IF FN CosinAngle(Nx,Ny,Nz,Px-Sx,Py-Sy,Pz-Sz)<0 THEN! 
"Normal vector must point to projection point!! 
Nx=-Nx! 
Ny=-Ny! 
Nz=-Nz! 
END IF! 
END IF! 
Dqe=Nx* (Qx-Sx) +Ny* (Qy-Sy) +Nz* (Qz-Sz) ! 

Spx=Sx-Qx+2*Dqe*Nx! 
Spy=Sy-Qy+2 *Dqe*Ny! 
Spz=Sz-Qz+2*Dqe*Nz! 

Mirror=FN CosinAngle (Spx, Spy, Spz,Px-Sx,Py-Sy,Pz-Sz) ! 

IF Mirror<0 THEN! 

Mirror=0! 
END IF! 

Bright =FN CosinAngle (Nx, Ny, Nz, Qx-Sx, Qy-Sy, Qz-Sz) ! 
ELSE! 

1 Determine mirror vector SP! 
IF K(n%,0,0)=10 THEN! 

Nx=Sx-K(n%,l,0)! 

Ny=Sy-K(n%,l,l)! 

Nz=Sz-K(n%,l,2)! 
END IF! 

IF K(n%, 0, 0)>=20 AND K(n%,0,0)<24 THEN! 
Nx=Help (n% , 4 ) *Ac+Help (n% , 1 ) *Bc! 
Ny=Help(n%,5)*Ac+Help(n%,2)*Bc! 
Nz=Help (n%, 6) *Ac+Help (n%, 3) *Bc! 

IF K(n%,0,0)>=22 THEN! 

N1=SQR (Nx*Nx+Ny*Ny+Nz*Nz ) ! 
IF NloO THEN! 

a= (Ac*K (n%, 2, 0) +Bc*K (n%, 3, 0) ) "2! 

a=a+ (Ac*K(n%, 2, 1) +Bc*K (n%, 3, 1) ) A 2! 

a= (SQR (a+ (Ac*K (n%, 2, 2) +Bc*K (n%, 3, 2) ) A 2) ) /Nl! 

Nx = Nx*a! 

Ny = Ny*a! 

Nz = Nz*a! 

b=SQR(Nx*Nx+Ny*Ny+Nz*Nz)/Help(n%,7)! 

Nx=K(n%,4,0)*b+Nx/b! 

Ny=K(n%,4,l)*b+Ny/b! 

Nz=K(n%,4,2)*b+Nz/b! 
ELSE! 

' If a cone angle:! 

Nx=K(n%,4,0)! 

Ny=K(n%,4,l)! 

Nz=K(n%,4,2)! 
END IF! 
END IF! 
END IF! 

IF K(n%,0,0)>=24 THEN! 

Nx=Ac*Help(n%,l)+Bc*Help(n%,4)+Cc*Help(n%,7)! 

Ny=Ac*Help(n%,2)+Bc*Help(n%,5)+Cc*Help(n%,8)! 

Nz=Ac*Help (n%, 3) +Bc*Help (n%, 6) +Cc*Help (n%, 9) ! 
END IF! 



35 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



IF FN CosinAngle(Nx,Ny,Nz,Px-Sx,Py-Sy,Pz-Sz) <0 THEN! 
' => Normal vector points to projection point! 
Nx=-Nx! 
Ny=-Ny! 
Nz=-Nz! 
END IF! 

N1=SQR (Nx*Nx+Ny*Ny4-Nz*Nz ) ! 
Nx = Nx/Nl! 
Ny = Ny/Nl! 
Nz = Nz/Nl! 
! 

Dqe=Nx* (Qx-Sx) +Ny* (Qy-Sy ) +Nz* (Qz-Sz ) ! 
SI 

Spx=Sx-Qx+2*Dqe*Nx! 
Spy=Sy-Qy+2*Dqe*Ny! 
Spz=Sz-Qz+2*Dqe*Nz! 
! 

Mirror=FN CosinAngle (Spx, Spy, Spz, Px-Sx, Py-Sy , Pz-Sz) ! 
! 

IF Mirror<0 THEN! 

Mirror=0! 
END IF! 
! 

Bright =FN CosinAngle (Nx, Ny, Nz, Qx-Sx, Qy-Sy, Qz-Sz) ! 
END IF! 
! 

IF Mat (K(n%,0,2), 4)>0 THEN! 

Mirror=l .5*Mirror A (30*Mat (K(n%, 0, 2) , 4) ) ! 
END IF! 
END SUB! 

The variables Ac, Be, and Cc contain the intersection point parameters 
for u, v, and w in case it is an object like a cylinder, cone, or ellipsoid. 
The normal vector is regulated and has a length of one. This is 
important for later calculations. Dqe represents the distance from the 
light source io the tangent plane. The formula for calculating Mirror, 
located at the end of the SUB program, has been arbitrarily defined and 
can be experimented with. When we have defined a dull surface, and 
Mat(n,4) is relatively small, the reflected light from the light source is 
equally small. 



36 



Abacus 2.4 Simulating Perception 



2.4.3 The Dark Side of the World 



Now that we have defined the formulas to our satisfaction, we can get 
to other things. We have the intersection point S of the visual ray with 
an object and the position of the light source Q. All we have to do is 
check whether the line from S to Q intersects with any object, and if 
this intersection point lies between S and Q. 



Figure 2.13 



The line Q-s acts as the direction vector. Because of the inaccuracy of 
the operation using real numbers, we check the intersection point 
calculation to see if parameter 1 of the line is greater than a threshold, 
which is dependent on the numerical presentation of the inaccuracy (we 
talked about this earlier). Because we didn't pay attention to this, the 
same object that lies on the intersection point is calculated as the object 
throwing the shadow only, because the calculation of the inequality 
came out 0.00005 instead of 0. 

Because there is no stray light in our computer world, the shadows are 
naturally solid black. Since this is undesirable, we assign every object a 
shadow brightness number between zero and one. 

The check in our program is very simple because we already have a 
SUB program that calculates the intersection point between a line and 
all objects. We must call this SUB program again, but this time the 
line runs from the intersection point to the light source. When we get 
an intersection point as a result, the point lies in the shadows; 
otherwise we can assign it a normal color. The program section could 
look like the following: 

1 =>Compute Brightness of the point => stacks 
CALL WhichBody (0,Px,Py,Pz,Rx,Ry,Rz, Original ! , False) t 
1 

IF Body% > THEN1 

CALL SetBrightness(Body%, Px,Py,Pz, Mirror, Original ! ) f 



37 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



RestLght (StackPtr%) =Mat (K(Body%, 0, 2) , 4) 5 

5 

IF Bright <=0 THEN5 
■ unlit: 5 
Bright . r=Mat (K (Body%, 0, 2) , 0) *Mat (K (Body%, 0, 2) ,3)5 
Bright.g=Mat(K(Body%,0,2),l)*Mat(K(Body%,0,2),3)5 
Bright .b=Mat (K (Body%, 0, 2) , 2) *Mat (K (Body%, 0, 2) ,3)5 

ELSE5 

Kp%=Body%5 

'Shadow ?5 
CALL WhichBody(Kp%,Sx,Sy,Sz,Qx-Sx,Qy-Sy,Qz-Sz, False, True) < 
SWAP Body%,Kp%5 



IF Kp%>0 AND la<l THEN5 
' in shadow: 5 
Bright . r=Mat (K (Body%, 0, 2) , 0) *Mat (K (Body%, 0, 2) , 3) 5 
Bright. g-Mat (K (Body%, 0, 2) , l)*Mat (K (Body%, 0, 2) ,3)5 
Bright .b=Mat (K(Body%, 0, 2) , 2) *Mat (K(Body%, 0, 2) , 3) 5 

ELSE5 

1 Mirror light source on interface: 5 
Bright=Bright* (1-RestLght (StackPtr%) ) 5 

IF Bright <Mat (K (Body% , , 2 ) , 3 ) THEN5 
Bright =Mat (K (Body%, 0, 2) ,3)5 

END IF5 

Bright. r=Bright*Mat (K (Body%, 0, 2) , 0) -(-Mirror* 
RestLght (StackPtr%) 5 

Bright . g=Br ight *Mat (K (Body% , , 2 ) , 1 ) +Mi rror * 
RestLght (StackPtr%) 5 

Bright .b=Bright*Mat (K (Body%, 0, 2) , 2) +Mirror* 
RestLght (StackPtr%) 5 
END IF5 
END IF5 

Now we must color in the point on the screen with the equivalent of 
the value from Bright. r (red), Bright. g (green), and Bright.b 
(blue). But we want to go a step further. We hope that you are not tired 
from all of these steps, because now it gets really interesting. 



2.4.4 Reflection 



As the last feature we should take a look at reflection. We can compute 
the reflected visual rays and their intersection point with an object. The 
problem remains of combining the different colors of the different 
surfaces. 

The duller a surface is, the harder it is to see the reflection of this 
object. In nature, reflections also lose some intensity, constantly 
changing the original color information. 



38 



Abacus 2.4 Simulating Perception 



We will proceed as follows: First we'll compute all of the intersection 
points and their color as in the above program section. We place this 
color on the stack. After the last reflection we take the color and 
combine it with the last color. We combine the result with the color 
before last, and so on, until we return to the first color. 

Compu t epo i n t : 1 

' =>Compute Brightness of the point => stackl 
Stack?- r% - StackPtr% + 11 

CALL WhichBody (0 , Px, Py , Pz, Rx, Ry, Rz , Original ! , False) 1 
1 

IF 3ody% > THEN? 

CALL SetBrightness (Body%, Px, Py, Pz, Mirror, Original ! ) 1 
RestLght (StackPtr%) -Mat (K (Body%, 0, 2) ,4)1 
1 

IF Bright <=0 THEN1 
* unlit: 1 
Bright. r=Mat(K(Body%, 0,2) , G) *Mat (K (Body%, 0, 2) ,3)1 
Bright. g-Mat (K (Body%, 0, 2) ,1) *Mat (K (Body%, 0, 2) , 3) 1 
Bright .b-Mat (K (Body%, 0, 2) ,2) *Mat (K (Body%, 0, 2) , 3) 1 
ELSE1 

Kp%=Body%1 

'Shadow ?1 
CALL WhichBody (Kp%,Sx, Sy, Sz, Qx-Sx, Qy-Sy, Qz-Sz, False, True)1 
SWAP Body%,Kp%1 
IF Kp%>0 AND la<l THEN1 
1 in shadow :1 
Bright. r-Mat (K (Body%, 0, 2) , 0) *Mat (K(Body%, 0, 2) ,3)1 
Bright. g=Mat (K (Body%, 0, 2) ,l)*Mat (K (Body%, 0, 2) ,3)1 
3right.b=Mat(K(Body%,0,2) , 2) *Mat (K (Body%, 0, 2) ,3)1 
EL3E1 

1 Mirror light source on inter face :1 
Bright=Bright* (1 -RestLght (StackPtr%) ) 1 
IF Bright<Mat (K(Body%,0, 2) ,3) THEN1 

Bright -Mat (K (Body%, 0, 2) ,3)1 
END IF1 

Bright . r-Bright *Mat (K (Body% , , 2 ) , ) +Mi rror x 
RestLght (StackPtr%) 1 

Bright. g=3right*Mat (K(Body%, 0,2) ,1) +Mirror* 
Re st Lgh t ( S t ackP t r % ) 1 

Bright ,b=Bright*Mat (K (Body%, 0, 2) , 2) -hMirror* 
Re s t Lgh t ( S t a c kP t r % ) 1 
END IF1 
END IFf 
1 

IF (RestLght (StackPtr%) >0) AND (StackPtr%<MaxStack% ) THEN1 
1 Determine Mirror interfaced 
1 Determine mirror vector to P-S:1 
Dqe=Nx* (Px-Sx) +Ny* (Py-Sy) +Nz* (Pz-Sz) 1 
Rx=Sx-Px+ 2*Dqe*Nx1 
Ry=Sy-Py+ 2 *Dqe* Ny 1 
Rz - S z - P z + 2 * Dqe * N z 1 
ci- 
St ack (StackPtr%, 0) -Bright, rl 
Stack (StackPtr%, 1) -Bright. gl 
Stack (StackPt r%, 2) -Bright . bl 



Falsel 



Px - 


Sxl 


Py - 


Syl 


Pz - 


5z1 


Orig 


.nal 



39 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



GOSUB Computepoint ' Recursion ! ! ! ! 5 

1 
Bright . r=Stack (StackPtr%, 0) +Stack (StackPtr%+l, 0) * 
RestLght (StackPtr%) SI 

Bright .g=Stack (Stack.Ptr%, 1) +Stack (StackPtr%+l, 1) * 
RestLght (StackPtr%) % 

Bright.b=Stack(StackPtr%,2)+Stack(StackPtr%+l,2)* 
RestLght (StackPtr%) f 
END IFfl 
ELSE! 

IF StackPtr% = THENf 
Bright. r=- If 
Bright. g=-lf 
Bright. b=-lf 
ELSEf 

Bright. r=0fl 
Bright. g=0fl 
Bright. b=0f 
END IFfl 
END IFfl 

Stack (StackPtr%, 0) ^Bright . rSI 
Stack (StackPtr% , 1 ) ^Bright . gf 
Stack (StackPtr% , 2 ) =Bright . bfl 
RestLght (StackPtr%) =0f 
StackPtr% = StackPtr%-11 
RETURNS 

This routine also contains the program section that was mentioned in 
the section describing shadows. The variables used were already 
discussed, so here we'll just introduce StackPtr%. In the main 
program, from which the calculated point is called, StackPt r% is set 
to -1. This increments by 1 for every reflection until there are no more 
reflections, or until the maximum stack depth (20) is reached. 



2.4.5 Bringing Color to the Screen 



The results of our calculations up until now have been three values that 
stand for the red, green, and blue hues of the color. Now we must 
somehow bring these colors onto the screen. Because we don't have 
many colors to insert, we must now figure out how to combine these 
colors until we get desired color. 

You may be thinking, "Hold it. HAM mode gives us 4096 colors to 
use, and that's more than enough." That's correct, but any one pixel 
can only take on one of 64 colors: 16 basic colors plus 16 colors by 
changing the red intensity, 16 colors by changing the green intensity, 
and 16 colors by changing the blue intensity. This gives us a total of 
64 colors. 

We aren't done combining colors. We base the displayed color 
combination on the pattern defined. The pattern itself is two-color: One 
color is established using the foreground color, and the other is 



40 



Abacus 



2.4 Simulating Perception 



established using the background color. To get different color 
combinations, we define different patterns, some with more pixels from 
one color, and some with fewer pixels on one color. The pattern 
automatically used by the operating system gives you a rectangle when 
you set a pointer to it in the Rast Port structure. 

Now we have another problem that we cannot ignore: which two colors 
do we combine to get the desired color combination? It's not easy. 
When you want to display a picture in monochrome (gray scales), all 
you need are two shades of gray. 

Problems occur when you switch to color display. Put the color in 
three dimensions: A red axis, a green axis, and a blue axis. The result is 
a cube that has one corner on the origin. To make the problem easier to 
visualize, here is an example: 

A study of the color green appears below. Because we must economize 
on memory space, our screen has only four colors: black, red, green, 
and yellow. We need red and green because the picture contains red and 
green objects. When we display the colors in a coordinate system 
(which can be two dimensional in this case), we get the following 
picture: 



Red 



Figure 2.14 



Yellow 




Combined yellow 
and red (green) 



Black A Green 

Combined black and red (green) 



When the yellow intensity is less than 0.5, the color black seems to 
work best. The second best color is either red or green, because these 
colors are closer to yellow than black is to yellow. This provides an 
intermediate color between black and yellow. When the yellow 
intensity is greater than 0.5, yellow works best. Red or green are the 
next best colors. When red or green is chosen, in which case they are 
equal, both colors arc the same distance from the desired color. The 
result can only be changed by increasing the number of the color. 

It would be unacceptable if the algorithm went through all of the pos- 
sibilities and took the best one. The routine in assembly language 
requires five seconds per pixel for 64 colors and 25 patterns. That 
means that one 320x200 picture would require more than three days to 



41 



2. The Basics of Ray Tracing Amiga 3D Graphic Programming 



execute. And the time needed for an equivalent program in 
BASIC... well, let's just say it'll take more time. 

Here's an alternative: Try the two colors whose hues are similar to the 
one you are searching for. The direction of the color vector must be 
tested for as well as its polar coordinates. Disadvantage: The calculation 
of the desired color in polar coordinates takes time. In addition, the 
result does not completely solve the problem. For example, to get a 
gray tone, you'd combine white and black instead of two shades of 
gray. Here a lot depends on the pattern itself, namely, the ratio in 
which the colors are mixed. 

We must admit that we haven't found the ideal algorithm. We've used 
the first (combining the two closest colors). When the basic colors are 
well distributed you get good results, especially in HAM mode. 

Because BASIC is not the fastest language, we programmed the algo- 
rithm in assembly language. It would be better if the entire tracer 
program was written in assembly language, but assembly language 
programs are harder for the average person to read and understand than 
BASIC programs. The program length also makes reading hard. 

The assembly routine is written with AssemPro. See the appendices 
for the source code (SetPoint.ASM) and a BASIC loader for those of 
you who do not have an assembler. If you want to implement this 
yourself, you must create PC-relative code with AssemPro. You 
must also write out the addresses of the three subprograms and the 
variables RastPort, Mode, MaxColors, Colors, RasterW, 
and RasterH, and these must be added to the BASIC subprogram 
InitSetPoint. The created code must be saved as Set Point . B. 
and the the routine can be loaded with InitSetPoint. The variables 
Rasterlnit and ColorPalette will be changed. The routine is 
called with: 

CALL OSSetPoint&(xl,yj,x2, y2, red* 1024, green*' 1024, blue* 1024) 

where (xl,yl) is the upper left comer and (x2,y2) is the lower right 
comer of the rectangle. The values for red, green, and blue must be 
between and 1024. These values should generally be given as integer 
values. 

The assumption for the OSSpoint routine is that the red, green, and 
blue values of the basic colors are stored in the array OSColor. This 
field is found directly behind the assembler routine and the values must 
be poked. Each element contains four values (16 bits): Number of the 
corresponding color register, red intensity* 1024, green intensity* 1024, 
and blue intensity* 1024. The number of the basic color must be in 
OSMaxColors. OSRastPort contains a pointer for the RastPort 
of the window or screen, OSMode contains the presentation mode, for 
example, $800 for HAM mode. OSRasterW and OSRasterH 



42 



Abacus 2.4 Simulating Perception 



contain the height and width of the window/screen because 
OSSetPoint takes its own clipping. 

To get a good color palette, you should put in the optimal color palette 
for each picture. Allow the picture to go through a long calculation and 
note how the colors come out. Then alter the color palette so that for 
each color there is the widest range of color shades. It would be best to 
use the HAM (Hold and Modify) mode. 



43 



2. Basics of Ray Tracing 



Amiga 3D Graphic Programming 



2.5 



Optimization 



Figure 2.15 



The algorithm we have been formulating so far works. We should add 
some improvements. This algorithm has a built-in feature for com- 
puting printout parameters that remain unchanged during calculation. 
The SUB program that executes this for us is called Init Shadows. 
The computed values are stored in the Help array, the elements in this 
array have different meanings for different objects. Help contains the 
normal vector for planes, and the denominator determinate for the basis 
transformation for cylinders, cones, and ellipsoids. 

The next step encountered is the intersection point calculation. Exam- 
ine the following diagram and imagine the objects are displayed on your 
screen: 




The objects take up a fairly large section of the screen. We can first 
establish a minimal rectangle in which all of the objects lie. Then our 
program needs to send out a visual ray for every point that lies inside of 
this rectangle. 

Next we draw a minimal rectangle for each object, so that the object 
lies completely within it. In our SUB program WhichBody we check 
if the actual visual ray passes through this rectangle. If it does, we 
calculate the intersection point. This check for the current point within 
the rectangle goes much faster than the intersection point calculation, 
it must execute more determinate calculations (cylinder, cone, 
ellipsoid). 

The rectangles for our above graphic can look like this example: 



44 



Abacus 



2.5 Optimization 



Figure 2.16 




The rectangles for the individual objects are narrow and the rectangle for 
the screen section is wide. Notice that the cube is assembled from six 
parallelograms (sides), but only the visible three are shown here, 
because otherwise it would make the diagram hard to follow. 

We can store the rectangle borders in an array, say MinMax. Each 
element of Mi nMax contains the following values: 

MinMax (n,0) = minimum x coordinate for object n 

MinMax (n,l) = minimum y coordinate for object n 

MinMax (n, 2) = maximum x coordinate for object n 

MinMax (n, 3) = maximum y coordinate for object n 

The subroutine which calculates these rectangles is initMinMax. For 
"round" objects (circular surfaces, cylinders, spheres, etc.), a rectangle 
or square is put around the object, and those corner points create the 
basis for the rectangle computation. Here you can put an octagon 
around an object and the rectangle calculations occur naturally. 

This optimization only helps us when we send out visible rays for 
testing. It doesn't help for reflected visual rays or shadow calculation. 
We can't take any optics for the reflected visual rays because neither the 
starting point of the reflected visual ray nor its direction is confirmed. 

But what about the shadows? The light source stays in the same posi- 
tion. The surface that lies in the shadows can be above everything, but 
it also cannot be confined to a plane, like the projection surface. When 
we calculate all objects relative to the light source instead of the 
rectangles, and establish minimums and maximums for both angles, we 
are dealing with shadows. True is tested to see if the polar coordinates 
of the intersection point lie inside the intervals set for each object. 

Do you understand what is going on? Instead of the cartesian coordi- 
nates (x,y,z), we can also give a point in polar coordinates as (a,b,d). 
a and b are angles and d is the distance from the coordinate origin. We 
can give an Amin and an Amax for each object so that for each point of 



45 



2. Basics of Ray Tracing Amiga 3D Graphic Programming 



the object the angle a lies between Amin and Amax. The same thing 
can be done for b by setting a Bmin and Bmax. 

When we determine in WhichBody whether an object casts a shadow 
on a point, you first compute the polar coordinates of the point 
(pa,pb,pd). Before you work through the intersection point 
calculation, test to see if pa lies between Amin and Amax and if pb 
lies between for Bmax and Bmin for this object. If this is not the case, 
this object cannot cast a shadow on the point and you can skip the 
intersection point calculation. 

We can also limit the minimum distance of an object from the light 
source. We can then test if the distance of the object from the light 
source is greater than the distance of the point from the light source. 
This would also mean that we can skip the intersection point calcula- 
tions. 

The problem comes from the angles location, which can usually lie 
between -Pi and +Pi. When an object lies on the boundary between 
+Pi and -Pi, you get an incorrect angle interval. In this case we must 
add an angle interval so that the angle lies between and 2* Pi. This 
increment must be kept for every object and must be considered during 
the test. The field that contains all of these values is called 
MinMaxLq, and its elements have the following meaning: 

MinMaxLq (n, 0) : increment for angle a 

MinMaxLq (n, 1) : minimum for angle a 

MinMaxLq (n, 2) : maximum for angle a 

MinMaxLq (n, 3) : increment for angle b 

MinMaxLq (n, 4 ) : minimum for angle b 

MinMaxLq (n, 5) : maximum for angle b 

MinMaxLq (n, 6) : minimum distance of object n from q 

This field is initialized in the subroutine initMinMaxLq. The test 
for MinMax and MinMaxLq in WhichBody is: 

SUB WhichBody (Kp%, Px,Py,Pz, Rx,Ry, Rz, Original !, Shadown ! ) STATIC! 
SHARED True, False, minmax% () , NumberK, minmaxlq ( ) , HelpO ,K() , 
xb%, yb%, Sx, Sy, Sz, Body%, Ac, Be, Cc, la, Threshold! 

1 => Body% = Nr the body under coordinates xb%,yb%, 
S (sx, sy, sz) ^Intersect point, la=intersection line! 
' => falls Typ>=20: 

'(ac,bc,cc) = transform Intersect points coordinates! 
la=-l! 
Body%=0! 
! 

IF Shadown! = True THEN ! 

CALL Calcablq(Anglea,Angleb, 0!, 0! ,Px,Py,Pz)! 
Dist=SQR(Rx*Rx+Ry*Ry+Rz*Rz)! 
END IF! 
! 

FOR n%=l TO NumberK! 

IF Original ! - True THEN! 
IF minmax%(n%,0)>xb% THEN! 
GOTO Nxtk! 



46 



Abacus 2.5 Optimization 



END IF? 

IF rrdnmax%(n%,l)>yb% THEN? 
GOTO Nxtk? 

END IF? 

IF minmax%(n%,2)<xb% THEN? 
GOTO Nxtk? 

END IF? 

IF minmax%{n%,3)<yb% THEN? 
GOTO Nxtk? 

END IF? 
END IF? 
? 
IF Shadown! = True THEN? 

CALL NormalAngle (Wa, Anglea+minmaxlq (n%, 0) ) ? 

CALL NormalAngle (Wb, Angleb+minmaxlq (n%, 3) ) ? 

IF Wa<minmaxlq(n%,l) THEN? 
GOTO Nxtk? 

END IF? 

IF Wa>minmaxlq(n% / 2) THEN? 
GOTO Nxtk? 

END IF? 

IF Wb<minmaxlq(n%,4) THEN? 
GOTO Nxtk? 

END IF? 

IF Wb>rriinmaxlq(n%,5) THEN? 
GOTO Nxtk? 

END IF? 

IF Dist<minmaxlq{n%, 6) THEN? 
GOTO Nxtk? 

END IF? 
END IF? 
? 
IF K(n%,0,0)=0 THEN? 

CALL IntersectpointP.lane (n%,Px, Py,Pz, Rx,Ry,Rz, 1) ? 

GOTO Wkok? 
END IF? 
IF K(n%,0,0)=l THEN? 

CALL IntersectpointTriangle (n%,Px, Py, Pz, Rx,Ry,Rz, 1, a, b) ? 

GOTO Wkok? 
END IF? 
IF K(n%,0,0)=2 THEN? 

CALL IntersectpointRectangle (n%, Px, Py, Pz, Rx, Ry, Rz, I, a,b) ? 

GOTO Wkok? 
END IF? 
IF K(n%,0 f 0)=3 THEN? 

CALL IntersectpointCircle (n%, Px,Py,Pz, Rx,Ry, Rz, 1, a, b) ? 

GOTO Wkok? 
END IF? 
IF K(n%,0,0)=4 THEN? 

CALL IntersectpointCircleSector (n%,Px, Py, Pz, Rx,Ry, Rz, 
l,a,b)? 

GOTO Wkok? 
END IF? 
IF K<n%,0,0)=5 THEN? 

CALL IntersectpointCircleRing(n%,Px,Py,Pz,Rx,Ry,Rz, l,a,bH 

GOTO Wkok? 
END IF? 
IF K(n%,0,0)=10 THEN? 

CALL IntersectpointSphere (n%, Px, Py, Pz, Rx, Ry, Rz, 1) ? 

GOTO Wkok? 
END IF? 
IF K(n%,0,0)=20 THEN? 



47 



2. Basics of Ray Tracing Amiga 3D Graphic Programming 



CALL IntersectpointCylinder (n%,Px,Py,Pz,Rx,Ry,Rz, l,a,b,c, 
Original! )! 

GOTO Wkok! 
END IFf 

IF K(n%,0,0)=21 THEN! 
CALL 
IntersectpointCylinderSegm(n%,Px,Py,Pz,Rx,Ry,Rz, 1, a,b, c, 
Original!)! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=22 THEN! 

CALL IntersectpointCone (n%, Px,Py,Pz, Rx,Ry, Rz, 1, a,b, c, 
Original!)! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=24 THEN! 

CALL IntersectpointEllipsoid (n%,Px,Py,Pz, Rx, Ry,Rz, 1, a, b, c, 
Original!)! 
END IF! 
Wkok:! 
' Work OK!! 
! 

IF (l>Threshold) AND (la<=0 OR Kla) AND (n%OKp% OR 
K{n%,0, 0)>=10) THEN! 
la-1! 
Body%-n%! 

IF K(n%, 0, 0) >=20 AND Kp%=0 THEN! 
Ac=a! 
Bc=b! 
Cc=c! 
END IF! 
END IF! 
Nxtk:! 
1 Next body! 
NEXT n%! 
! 

IF Rody%>0 AND Kp%=0 THEN! 
Sx=Px+la*Rx! 
Sy=Py+la*Ry! 
Sz=Pz+la*Rz! 
END IF ! 
END SUB! 

We leave you with a few words about calculation time. A super com- 
puter like a Cray needs a good twenty minutes to compute a picture. 
The tracer program is written in BASIC mainly because BASIC is an 
easy language to understand. BASIC is also a slow language. Picture 
calculation requires lots of time. Luckily the Amiga multitasks so that 
you aren't inhibited during calculation. 

We recommend that you compile the tracer program or the one you 
create for this routine (see Chapter 8 for compiling instructions). That 
lowers the computation time for a 320x200 picture to under a day. 
When you have defined only a few unreflected objects, the computation 
time goes under a few hours. Rewriting this routine in assembly 
language will speed things up considerably. 



48 



3. 

The Tracer 

Program 



Abacus 3. The Tracer Program 



3 . The Tracer Program 



Now that we have discussed the basic algorithms required for three 
dimensional graphics, we'd like to show you our results. This chapter 
contains our realization of a ray tracing program. Before describing the 
routine we'd like to point out that the aim of this book is to teach you 
how to program three dimensional graphics. This book is not a 
programming tutor in itself. The routines are written in modular form 
so they can easily be adapted for use in your own programs. The 
optional disk contains the separate modules saved in ASCII format so 
they may be easily merged into your own program code. 



3.1 Wire Models 



Now that you've learned some of the theory of how ray tracing works, 
this section explains how to make three dimensional wire models. 



3.1.1 From 3D to 2D 



This wire model is used to display the objects on the screen before 
calculating the shadows. This saves a good deal of time and allows the 
objects to be placed on the screen in the best manner. 

To display our objects, we must project all of the three dimensional 
points whose X, Y and Z coordinates were given onto the screen. 
Points that make up the room must also be put on the plane. The 
points projected on a plane can then be displayed on the screen. 

It must be obvious from the screen display whether an object is placed 
in front of or behind another object. We must also create a perspective 
effect, so the computer gives the most realistic scene possible. 

We first fix a stationary point inside the computer world. We do this by 
giving the coordinates of our stationary point with the variables Px, 
Py, andPz. We named the given point Projection point. 

Where do we see the scene from? With only a point in the room we 
cannot locate the direction of vision. We place a second point that is 



51 



3. The Tracer Program 



Amiga 3D Graphic Programming 



also appropriate for the vision direction. We call this point the Main 
point, whose coordinates are Hx, Hy, and Hz. 

We place ourselves at the projection point and look in the direction of 
the main point. 

The main point does more than determine the vision direction. This 
point is also a point of our projection plane — the plane on which our 
points are projected. Before the points are given on the screen, the 
projection plane must first be constructed. 

But the projection point is not totally passive. The line through the 
projection point and the main point is perpendicular to the projection 
plane: 



Figure 3.1 




Projection point 



Main point 

Projection plane 



The line PM (projection point/main point) helps us determine the 
rotation angle around the coordinate axes, around which the projection 
plane must rotate so that it coincides with the YZ plane. 

We first place the main point at the origin. We do this because the 
coordinates of all the points are taken from the coordinates of the main 
point. 

The following diagram illustrates how we determine the rotation angle: 



52 



Abacus 



3.1 Wire Models 



Figure 3.2 




As you can see, the relationships for the angle Alpha (Z axis) and the 
angle Beta (Y axis) are: 

Sin (alpha) = (Px-Hy) /Dl 
Cos (alpha) = (Px-Hx) /Dl 



Sin (beta) = (pz-Hz) /DPH (DPH 
point to main point) 
Cos (beta) = Dl/DPH 



Distance from projection 



The angle can be calculated using the ATN (arctangent) function of 
AmigaBASIC. This is possible because the tangent of an angle is also 
defined as the quotient of the sine and cosine of the angle: 

Angle = ATN (Sin/Cos) 

The angle from the X axis must be set very close to 0. As the diagram 
shows, when the projection plane lies in the YZ plane or the projection 
points lies on the X axis, the rotation angle does not need to be 
calculated any more. 

The InitialP routine calculates the position of the main point and 
the projection point of the required rotation angle, as well as the 
distance from the main point to the projection point. 

InitialP: SI 

D1=SQR ( (Px-Hx) A 2+ (Py-Hy) A 2) 1 

DPH-SQR ( (Px-Hx) A 2+ (Py-Hy) A 2+ (Pz-Hz) A 2) f 

IF D1=0 THEM 

Sina=05 

Cosa=l<i 
ELSE! 

Sina= (Py-Hy) /D11 

Cosa= (Px-Hx) /Dl! 
END IF! 
! 

IF DPH=0 THEN! 

Sinb=0! 

Cosb=l! 



53 



3. The Tracer Program 



Amiga 3D Graphic Programming 



ELSE1 

Sinb=(Pz-Hz)/DPM 

Cosb-Dl/DPHSI 
END IFfl 



Sinc=0 
Cosc=l 



Z-Axis angle notl 
solely determined here^l 



IF Cosa=0 THEN1 

Alpha=Pd21 
ELSEH 

Alpha=ATN (Sina/Cosa) 
END IF 
1 

IF Cosa<0 THENSI 

Alpha = Alpha+PiH 
END IFfl 
SI 

IF Cosb=0 THEN! 

Beta=Pd2<fl 
ELSE1 

Beta^ATN (Sinb/Cosb) 1 
END IFf 

IF Cosb<0 THEN1 
Beta = Beta + Pifl 

END IFfl 
I 

Gamma=0<I 
RETURNS 



compute cosinem and Sinel 
anglef 



When we calculate the rotation angle, we need to make sure that the 
point rotates around the coordinate axes. We must subject every point 
to the same rotation as the projection plane so that they lie on the yz 
plane. 

How do you rotate a point? Look at this illustration: 



Figure 3.3 




Q'x 



The point Q rotates around the angle alpha. Q ' is the point rotated 
around the angle alpha. It is described by the following relationships: 



Sin(p) = Qy/r 



Sin(CC-P) = Q'y/r 



54 



Abacus 



3.1 Wire Models 



Addition 
theorem: 

Substitutin 



Cos (P) = Qx/r 



Cos (a~P) = Q'x/r 



Insert this in the addition theorem and you get the formula for the 
rotation of a point around the angle alpha. 

Cos(P-Ot) = Cos<P) *Cos ((X)+Sin(P) *Sin(Ot) 
Sin(P-a) - Sin(P) *Cos (a)-Cos (P) *Sin(a) 

C'x/r - Cos(CC)*Qx*r + Sin((X)*Qy*r 
Q'y/r = Cos<(X)*Qy*r - Sin((X)*Qx*r 



Q'x = Cos(Ot)*Qx + Sin(CC)*Qy 
Q'y = Cos((X)*Qy - Sin(Ot)*Qx 

Now we need to rotate the points around all three coordinate axes 
according to the above formula. For example, we rotate a point around 
the Z axis, and the Z coordinate does not change. It is the same when 
rotating around the other two axes. 

The rotations are shown in the following diagram: 



Figure 3 4 





(x3,y3, 



You should remember that for rotation around the Y axis the previously 
computed coordinates for the rotation around the Z axis are used. The 
results of the Y rotation are used for the rotation around the X axis. 

Now we can concentrate on perspective. We examine the line through 
the projection point and the points that rotate around the coordinate 
axes: 



55 



3. The Tracer Program 



Amiga 3D Graphic Programming 




Figure 3.5 



I Projection plane | 



As you can see, the projection point now has the coordinates 
(dph,0,0). We determine the rotation angle around the Z and Y axes 
from the projection-main point line so that the projection plane lies on 
the YZ plane. Because the line PH is perpendicular to this plane and the 
main point again lies on the coordinate origin, this means that the 
projection point lies in the range DPH on the X axis. 

Now we look at the intersection points of the line with the plane. Each 
of these intersection points places a displayed point there. The 
coordinates of the individual intersection points can also be used for our 
screen output. 

How do you determine these intersection points? We see the line 
equation of the line projection point — displayed point: 



x 



Qx 

Y = Qy I 
Z Qz 



(Px-Qx) 
(Py-Qy) 
(Pz-Qz) 



We know that the intersection point must have the X coordinate 
because the X coordinate of all points on the YZ plane is (we 
determined through the rotations that the projection plane lies in the 
YZ plane). 

Together with the coordinates of the projection points and the X 
coordinate of the intersection point we can set up the following 
relationships: 



X 

Y = 
Z 


Qx (DPH-Qx) 
= Qy + t * (0-Qy) 
Qz (0-Qz) 




X = 


= Qx + t * (DPH-Qx) -- 

t = 


= 

= -Qx/ (DPH-Qx) 



By inserting from t and converting the remaining equations you get the 
Y and Z coordinates of the intersection points (Q ' is already rotated 
around all 3 axes): 



56 



Abacus 3.1 Wire Models 



Y = Q'y*DPH/ (DPH-Qx) 
Z = Q'z*DPH/ (DPH-Qx) 

These are our screen coordinates. We must now consider the Z 
coordinate of the intersection point as the Y screen coordinate, and the 

Y coordinate of the intersection point as the X coordinate of the screen. 

The following routine does the entire 3D/2D conversion, the rotating of 
the coordinate axes, and the perspective transformation. The points 
returned then must be displayed on the screen. 

SUB Projection (Px%, Py%, x,y, z) STATIC! 

SHARED Sina, Sinb, Sine, Cosa, Cosb, Cose, DPH, Hx, Hy, Hz! 

• 3D coordinates (x,y,z) to 2D (Px%,Py%) = Screen! 
! 

xl={x-Hx) *Cosa+ (y-Hy) *Sina ' Z-Axis rotation! 

yl= (y-Hy) *Cosa- (x-Hx) *Sina! 

x2=xl*Cosb+(z-Hz)*Sinb * Y-Axis rotation! 

z2= (z-Hz) *Cosb-xl*Sinb! 

y3=yl*Cosc+z2*Sinc ' X-Axis rotation! 

z3=z2*Cosc-yl*Sinc! 
! 

IF DPHOx3 THEN! 

Px%=FN Xscale((y3*DPH)/(DPH-x2) ) -4 ' Intersecting point 
with projection point ! 

Py%=FN Yscale( (z3*DPH)/(DPH~x2) ) -2 • scaling! 

ELSE! 

Px% = FN Xscale(O) -4 ' Subtraction of 4 and 2 based on 
drawing! 

Py% = FN Yscale(O) -2 ' in a GIMMEZEROZERO-Window (BASIC- 
Window)! 

END IF! 
END SUB ! 

When examining this routine you will notice the following functions: 

FN XSclae (x) = (x+PictureX) * Picturewidth and 
FN YScale (y) = (PictureY-y) * Pictureheight 

They make sure that the intersection points with the YZ plane are 
shown with the correct enlargement. To understand what this user 
function does, we must first clarify the meaning of the variable;*: 

Picturewidth and Pictureheight act as the enlargement 
(magnification) factors in the X and Y directions. PictureX and 
Pict ureY give the size of the window section whose contents should 
be enlarged: 



57 



3. The Tracer Program 



Amiga 3D Graphic Programming 



Figure 3.6 





f 


Si£X_ 


-^ 




Pic3Nj^ 

- . _J 

















*>5*qY 





Pi&C 




















« 


» 





Screen 



Screen 



The larger PictureX and PictureY, the larger the area of points 
that must be presented on the screen. PictureX and PictureY are 
calculated as follows: 

PictureX - RasterW2% / Picturewidth 
PictureY - RasterH2% / Pictureheight 

RasterW2% and RasterH2% are the screen coordinates of the mid 
point (For a 320x200 screen RasterW2% = 160 and RasterH2% = 
100). 

PictureX and PictureY get larger as Picturewidth and 
Pictureheight get smaller, and vice versa. 

xScale and Y Scale ensure that the origin of the coordinate system 
(= transformed main point) transforms to the midpoint of the screen. 

This occurred because the X coordinate of the intersection point is added 
to PictureX. Remove PictureY from the Y coordinate of the 
intersection point because the Y coordinates cross from top to bottom, 
not from bottom to top as in Cartesian coordinates. 

Multiply the coordinates by the enlargement factors to make the points 
correct for the screen. 

Until now we have always maintained that a main point and a 
projection point would be given. These two points are basically 
sufficient to develop a completely functioning 3D/2D routine. 

These points can be changed in a program. First the program must be 
interrupted and one or more program lines changed, for example, to 
give new coordinates for the center point. 

You can change the main point in the following routine, give a new 
projection point, change the rotation angle in degrees (not radians), and 
increase or decrease the distance DPH. A very small dph distorts the 
three dimensional presentation on the screen, while a large DPH loses 
the central perspective effect (the picture is in parallel perspective). 



58 



Abacus 3.1 Wire Models 



InputH:! 

Status$ = " Status: Main point "^-CHR$ (0) SI 

CALL SetWindowTitles& (NWBase& , SADD (Status$) , 0) 1 
1 

GOSUB DeleteMenul 
1 

LOCATE 10,11 

PRINT " Main point: "SI 
1 

LOCATE 12, If 

PRINT " Hx = ";! 

CALL Formlnput (Hx, 30 ! , -1E+14 , 1E+14) SI 
SI 

LOCATE 13,11 

PRINT " Hy = ";SI 

CALL Formlnput (Hy, 30 ! , -1E+14, 1E+14) SI 
SI 

LOCATE 14,11 

PRINT " Hz = ";! 

CALL Formlnput (Hz, 30 ! , -1E+14 , 1E+14) SI 
SI 

GOSUB Initial! 

Newone! = TrueSI 

CLSSI 

GOSUB MakeMenuSI 
RETURNSI 
'SI 
InputP:SI 

Status$ = " Status: Projection point"+CHR$ (0) SI 

CALL SetWindowTitlesS (NWBaseS , SADD (Status$) ,0)1 
1 

GOSUB DeleteMenul 
1 

LOCATE 10,11 

PRINT " Projection point: "1 

1 

LOCATE 12,11 

PRINT " Px = ";1 

CALL Formlnput (Px, 30! , -1E+14, 1E+14) 1 
1 

LOCATE 13,11 

PRINT " Py = ";1 

CALL Formlnput (Py, 30 ! , -1E+14 , 1E+14) 1 
1 

LOCATE 14,11 

PRINT " Pz = ";1 

CALL Formlnput (Pz, 30 ! , -1E+14, 1E+14) 1 

1 

GOSUB InitialPl 

Newone! = Truel 

CLSl 

GOSUB MakeMenu 1 
RETURN! 
'! 
InputDPH:! 

Status$ = " Status: Spacing"+CHR$ (0) 1 

CALL SetWindowTitles& (NWBaseS , SADD (Status$) , 0)1 

1 

GOSUB DeleteMenul 

1 

LOCATE 10,11 

PRINT " Spacing of projection surface = ";! 



59 



3. The Tracer Program Amiga 3D Graphic Programming 



CALL Formlnput (DPH, 30 I , -1E+14, 1E+14) 1 
1 

GOSUB Initia.11 

Newone! = Truel 

CLS1 

GOSUB MakeMenul 
RETURNS! 
'1 
InputAngle:1 

Status$ = " Status: Enter angle of rotation"+CHR$ (0) 1 

CALL SetWindowTitlesS (NWBase& , SADD (Status$ ) ,0)! 

1 

GOSUB DeleteMenuf 
1 

a=FN Deg (Alpha) 1 

b=FN Deg (Beta) 1 

c-FN Deg (Gamma) 1 

1 

LOCATE 10,11 

PRINT " Angle of rotation (a,_,c): "1 
SI 

LOCATE 12,11 

PRINT " Alpha (Z-Axis) = ";1 

CALL Formlnput (a, 30 ! , ! , 360 ! ) SI 
SI 

LOCATE 13,11 

PRINT " Beta (Y-Axis) = ";1 

CALL Formlnput (b, 30 ! , ! , 360 ! ) 1 
1 

LOCATE 14,11 

PRINT " Gamma (X-Axis) = ";1 

CALL Formlnput (c, 30 ! , ! , 360 ! ) 1 
1 

Alpha=FN Rad(a)1 

Beta^FN Rad (b) 1 

Gamma =FN Rad(c)1 
1 

GOSUB Initiall 

Newone! = Truel 

CLS1 

GOSUB MakeMenul 
RETURN1 
'End of Draw-Input . ascl 

When changing the main point, the distance DPH or the rotation angle, 
you should be careful because the position of the projection point is 
also changed. The main point is shown as the basis point now. 

In Initial, the data of the new projection point is computed: 

* * Input-Routine *1 

'1 

Initial:! 

WHILE Alpha<01 

Alpha = Alpha + Pm21 
WEND1 
WHILE Beta<01 

Beta = Beta + Pm21 
WEND1 



60 



Abacus 3.1 Wire Models 



WHILE Gamma<0! 

Gamma = Gamma + Pm2! 
WEND! 
WHILE Alpha>Pm2! 

Alpha = Alpha - Pm2! 
WEND! 
WHILE Beta>Pm2! 

Beta = Beta - Pm2! 
WEND! 
WHILE Gamma>Pm2! 

Gamma = Gamma - Pm2! 
WEND! 

Sina=SIN (Alpha)! 
Cosa^COS (Alpha)! 
Sinb=SIN (Beta) ! 
Cosb=COS(Beta)! 
Sinc=SIN (Gamma)! 
Cosc=COS (Gamma) ! 
! 

Px=Hx+DPH*Cosa*Cosb ' Projection point basedon the ! 
Py=Hy+DPH*Sina*Cosb ' main point and the spacings! 
Pz=Hz+DPH*Sinb ' DPH and Alpha, Beta and Gamma! 
RETURN ! 



We can also move around the main point with the projection point, 
which gives our stationary point. 



3.1.2 Objects and Surfaces 



Now that we can display points from the space onto the screen, we 
want to present these points as objects and surfaces. 

The principle here is very simple. From given information about the 
objects and surfaces you calculate specific pixels and project these 
pixels on the screen. To complete the particular object, the program 
draws lines from one pixel to the next ("connecting the dots" using 
these lines). 

We get this information about the individual bodies and surfaces from 
the array K() which was dimensioned with Dim K(NumberK,5,2). The 
following diagrams show you how the individual array elements must 
look or which values they must contain to present a certain body or 
surface: 



61 



3. The Tracer Program 



Amiga 3D Graphic Programming 



Plane: K(n%,0,0) - o 

o - K <n%, 1, . .) 

a - X <n», 2, . .) 

b - K <n%, 3, . .) 




Figure 3.7 



Triangle: K (n%, 0,0) =1 
a = K(n%, 1, . 



Figure 3.8 




Figure 3.9 



Rectangle: K)n%,0 f 0) = 1 

a = K(n%, 1, . . ) 

b = K(n%, 2, . . ) 

c = K (n%, 3, . . ) 




62 



Abacus 



3.1 Wire Models 



Circle (Ellipse) : K (n%,0,0) = 3 



Figure 3.10 



(n%, 


1, . •) 


(n%, 


2, . .) 


(n%, 


3, . .) 




Circle segment: K (n%,0,0) = 4 



Figure 3.11 



o = K(n%, 


1 


. .) 


a - K(n%, 


2 


. .) 


b = K(n%, 


3 


. .) 


K(n%, 5,0) 


= 


starting angle 


K(n%,5,l) 


= 


ending angle 




63 



3. The Tracer Program 



Amiga 3D Graphic Programming 



Sphere: K(n%,0,0) = 

o - K(n%, 1, . .) 
r = K(n%, 2, 0) 



10 



Figure 3.12 




Circular ring : K (n%,0,0) 



Figure 3.13 



o = K(n%, 
a = K(n%, 
b = K(n%, 



.) 

.) 
.) 



i K(n%,5 


0) 


= starting angle 




K(n%,5 


1) 


= endinc 


angle 




K(n%, 4 


0) 


= inner 


radius 




K(n%, 4 


1) 


= outer 


radius 






X/ 


/Mb 




































♦* / 










* * 










; 


^ 








»* »* 


,* 


y 'y^ o 








>6 fth 










HP* 



64 



Abacus 



3.1 Wire Models 



Cylinder: K(n%,0,0) = 20 
= K(n%, 1, . . ) 
a = K(n%, 2, . . ) 
b = K(n%, 3, . .) 



Figure 3.14 




Figure 3.15 



Cylinder segment : K (n%,0,0) = 21 

•) K(n%,5,0) = starting angle 



M 


= K(n%, 
= K(n%, 


2, 
3, 


. ■) 
. -) 


K(n%,5, 


i) 


= end 


ing 


angle 


h 


- K(n%, 
X 


4, 


. .) 


/ 


/. 








_/h/ 


^ 


/ 


/ a4 






fckSr 






A 
































/ 


















y 


















** 












o 






♦* 
** 








— ► 



65 



3. The Tracer Program 



Amiga 3D Graphic Programming 



Figure 3.16 



Cone : 


K(n%, 0, 


0) = 


= 22 


o = 


K(n%, 1, 






a = 


K(n%, 2, 






b = 


K(n%, 3, 






h = 


K(n%, 4, 








Ellipsoid: K(n%,Q,Q) = 24 



Figure 3.17 



= K(n%, 


1, . .) 


a = K(n%, 


2, . .) 


b = K(n%, 


3, . .) 


c = K(n%, 


4, . .) 




The following routines draw the characteristics of the individual objects 
and surfaces: 

DrawPlane:5 

CALL 
Projection(Xp%,Yp%,K(n%,2,0)+K(n%,l,0) ,K(n%,2,l)+K(n%, 1, 1) ,K(n%, 
2,2)+K(n%,l,2))fl 

CALL Moves (RastPort&, Xp%, Yp%) 1 

CALL Projection<Xp%,Yp%,K<n%,l,0),K(n%,l,l) , K (n%, 1 , 2) ) \ 



66 



Abacus 3.1 Wire Models 



CALL Draws (RastPortS, Xp%,Yp%) SI 

CALL 
Projection (Xp%,Yp%,K(n%, 3, 0)+K(n%, 1,0) ,K(n%, 3, 1) +K (n%, 1, 1) ,K (n%, 
3,2)+K(n%,l,2))SI 

CALL Draws (RastPortS, Xp%, Yp%) SI 
RETURNS 
'St 
DrawTriangle: SI 

CALL Projection (xl%,yl%,K(n%, 1,0) ,K(n%,l,l) ,K(n%,l,2) ) SI 

CALL Moves (RastPortS, xl%, yl%) SI 

CALL 
Projection(Xp%,Yp%,K(n%,2,0)+K(n%,l,0) , K (n%, 2, 1) +K (n%, 1, 1) ,K (n%, 
2,2)+K(n%,l,2))SI 

CALL Draws (RastPortS, Xp%, Yp%) SI 

CALL 
Projection(Xp%,Yp%,K(n%,3,0)+K(n%,l,0) , K (n%, 3, 1) +K (n%, 1, 1) ,K (n%, 
3,2)+K(n%,l,2))SI 

CALL Draws (RastPortS, Xp%,Yp%) SI 

CALL Draws (RastPortS, xl%,yl%) SI 
RETURNS 
'SI 
DrawRectangle : SI 

CALL Projection (xl%,yl%,K(n%, 1,0) , K (n%, 1, 1) ,K (n%, 1, 2) ) SI 

CALL Moves (RastPortS, xl%,yl%) SI 

CALL 
Projection (Xp%,Yp%,K(n%, 2, 0)+K(n%, 1,0) , K (n%, 2, 1 ) +K (n%, 1, 1 ) , K (n%, 
2,2)+K(n%,l,2))SI 

CALL Draws (RastPortS, Xp%,Yp%) SI 

Dx=K(n%,2,0)+K(n%,3,0)+K(n%,l,0)f 

Dy=K(n%,2,l)+K(n%,3,l)+K(n%,l,l)SI 

Dz=K(n%,2,2)+K(n%,3,2)+K(n%,l,2)SI 

CALL Projection (Xp%, Yp%,Dx, Dy, Dz) SI 

CALL Draws (RastPortS, Xp%,Yp%) SI 

CALL 
Projection (Xp%,Yp%,K(n%, 3, 0)+K(n%, 1,0) ,K(n%, 3, 1) +K (n%, 1, 1) ,K (n%, 
3,2)+K(n%,l,2))SI 

CALL Draws (RastPortS, Xp%,Yp%) SI 

CALL Draws (RastPortS, xl%,yl%) SI 
RETURNSI 
'SI 
DrawCircle:SI 

CALL 
Projection(Xp%,Yp%,K(n%,l,0)+K(n%,2,0) , K (n%, 1 , 1 ) +K (n%, 2, 1) , K (n%, 
l,2)+K(n%,2,2))SI 

' S1N(0) = and COS(0) = 1 goto K(n%,3,..), and K(n%,2,..) 
takes overSI 

CALL Moves (RastPortS, Xp%,Yp%) SI 

w=Pm2 /NumberSegment sSI 

D=wSI 

Repeatl:SI 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w)SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%, 3,2)*SIN(w) SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Draws (RastPortS, Xp%,Yp%) SI 
w = w+DSI 

IF (w<=Pm2+D/2) THEN GOTO Repeatl:f 
RETURNSI 
•SI 
DrawCircleSector : SI 

CALL Projection (xl%,yl%,K(n%, 1,0) ,K(n%,l,l),K(n%,l,2))SI 

w=K(n%,5,0)SI 



67 



3. The Tracer Program Amiga 3D Graphic Programming 



Dx=K (n%, 1, 0) +K (n%, 2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) 31 
Dy=K (n%, 1, 1) +K (n%, 2, 1) *COS (w) +K (n%, 3, 1) *SIN (w) f 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)3I 
CALL Projection (Xp%,Yp%,Dx,Dy,Dz) 31 
CALL Moves (RastPortS, xl%, yl%) 31 
CALL Draws (RastPortS, Xp%, Yp%) 31 
D=Pm2/NumberSegments1 
WHILE w<K(n%,5,l)3I 

w = w+D3I 

IF w>K(n%,5,l) THEN3I 
w=K(n%,5,l)3I 

END IF3I 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w)3I 

Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)3I 

Dz=K (n%, 1, 2) +K (n%, 2, 2) *COS (w) +K (n%, 3, 2) *SIN (w) 5 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) 31 

CALL Draws (RastPortS, Xp%, Yp%) 31 
WENDf 

CALL Draws (RastPortS, xl%, yl%) 31 
RETURNS 
'31 

DrawCircleRing:3I 
w=K(n%,5,0)3[ 

Dx=K(n%,l,0) + (K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w) ) *K (n%, 4, 0) 31 
Dy=K(n%,l,l) + (K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w) ) *K (n%, 4 , ) 31 
Dz=K(n%,l,2) + (K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w) ) *K (n%, 4 , 0) 31 
CALL Projection (Xua%, Yua%, Dx, Dy, Dz) 31 

Dx=K (n%, 1, 0) + (K(n%, 2, 0) *COS (w) +K (n%, 3, ) *SIN (w) ) *K (n%, 4 , 1 ) 31 
Dy=K(n%,l,l) + (K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w) ) *K (n%, 4 , 1 ) 31 
Dz=K(n%,l,2) + (K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w) ) *K (n%, 4 , 1 ) 31 
CALL Projection (Xoa%, Yoa%, Dx, Dy, Dz) 31 
CALL Moves (RastPortS, Xua%, Yua%) 31 
CALL Draws (RastPortS, Xoa%, Yoa%) 31 
D=Pm2/NumberSegments3I 
WHILE w<K(n%,5,l)3I 

w = w+D3I 

IF w>K(n%,5,i) THEN! 
w=K(n%, 5,1)31 

END IF3I 

Dx=K(n%,l,0) + (K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w) ) *K (n%, 4, 0) 31 

Dy=K(n%,l,l)MK(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w))*K(n%,4,0)3l 

Dz=K(n%,l,2) + (K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w))*K(n%, 4,0)31 

CALL Projection (Xu%, Yu%, Dx, Dy, Dz) 31 

Dx=K(n%,l,0) + (K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w) )*K(n%, 4,1)31 

Dy=K(n%,l,l) + (K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w))*K(n%,4,l)3I 

Dz=K(n%,l,2) + (K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w))*K(n%,4,l)3I 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) 31 

CALL Moves (RastPortS, Xua%, Yua%) 31 

CALL Draws (RastPortS, Xu%,Yu%) 31 

CALL Moves (RastPortS, Xp%,Yp%) 31 

CALL Draws (RastPortS, Xoa%, Yoa%) 31 

Xua%=Xu%1 

Yua%=Yu%3I 

Xoa%=Xp%3[ 

Yoa%=Yp%1 
WEND3I 

CALL Moves (RastPortS, Xua%,Yua%) 31 
CALL Draws (RastPortS, Xoa%, Yoa%) 31. 
RETURNS 



DrawSphere : 31 

D=Pm2/NumberSegments31 



68 



Abacus 3.1 Wire Models 



FOR wl=-Pd2+D TO Pd2-D/2 STEP DSI 
Dx=K(n%,l,0)SI 

Dy=K (n%, 1, 1) +K (n%, 2,0) *COS (wl) SI 
Dz=K(n%,l,2)+K(n%,2,0)*STN(wl)SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Moves (RastPortS , Xp%, Yp%) SI 
FOR w2=D TO Pm2+D/2 STEP Df 

Dx=K (n%, 1, 0) +K (n%, 2, 0) *SIN (w2) *COS (wl ) SI 
Dy=K(n%,l,l)+K(n%,2,0)*COS(w2)*COS(wl)SI 
Dz=K(n%,l,2)+K(n%,2,0)*SIN(wl)SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Draws (RastPortS, Xp%, Yp%) SI 
NEXT w2SI 
NEXT wlSI 

FOR wl=-Pd2+D TO Pd2-D/2 STEP DSI 
Dy=K(n%,l,l)SI 

Dz=K(n%,l,2)+K(n%,2,0)*COS(wl)SI 
Dx=K(n%,l,0)+K(n%,2,0)*SIN(wl)SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Moves (RastPortS , Xp%, Yp%) SI 
FOR w2=D TO Pm2+D/2 STEP DSI 

Dy=K(n%,l,l)+K(n%,2,0)*SIN(w2)*COS(wl)SI 
Dz=K (n%, 1 , 2) +K (n% , 2 , 0) *COS (w2 ) *COS (wl ) SI 
Dx=K(n%,l,0)+K(n%,2,0)*SIN(wl)SI 
CALL Projection (Xp%,Yp%, Dx,Dy,Dz) SI 
CALL Draws (RastPortS, Xp%, Yp%) SI 
NEXT w2SI 
NEXT wlSI 
RETURNSI 
'SI 
DrawCylinder : SI 

Dx=K(n%,l,0)+K(n%,2,0)SI 

Dy=K(n%,l,l)+K(n%,2,l)SI 

Dz=K(n%,l,2)+K(n%,2,2)SI 

CALL Projection (Xua%, Yua%, Dx, Dy, Dz) SI 

Dx=K(n%, 1, 0)+K(n%,2, 0)+K(n%,4, 0) SI 

Dy=K(n%,l,l)+K(n%,2,l)+K(n%,4,l)SI 

Dz=K(n%,l,2)+K(n%,2,2)+K(n%,4,2)SI 

CALL Projection (Xoa%, Yoa%, Dx, Dy, Dz) SI 

D=Pm2/NumberSegmentsSI 

FOR w=D TO Pm2+D/2 STEP DSI 

Dx=K (n%, 1, 0) +K (n%, 2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)SI 
Dz=K(n%,l,2) fK(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)SI 
CALL Projection (Xu%, Yu%, Dx, Dy, Dz) SI 

Dx=K (n%, 1, 0) +K (n%, 2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) +K (n% , 4 , 0) SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%, 3,1) *SIN (w) + K (n%, 4 , 1 ) SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2) *SIN (w) +K (n%, 4 , 2) SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz)SI 
CALL Moves (RastPortS, Xua%, Yua%) SI 
CALL Draws (RastPortS , Xu%, Yu%) SI 
CALL Draws (RastPortS, Xp%,Yp%) SI 
CALL Draws (RastPortS, Xoa%,Yoa%) SI 
Xua%=Xu%SI 
Yua%=Yu%SI 
Xoa%=Xp%SI 
Yoa%=Yp%SI 
NEXT wSI 
RETURNSI 
'SI 

DrawCylinderSegm:SI 
w=K(n%,5,0)SI 



69 



3. The Tracer Program Amiga 3D Graphic Programming 



Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3, 0) *SIN(w)SI 
Dy=K (n%, 1, 1) +K (n%, 2, 1) *COS (w) +K (n%, 3,1) *SIN (w) SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2) *SIN(w)SI 
CALL Projection (Xua% , Yua%, Dx, Dy, Dz ) \ 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w)+K(n%, 4,0) SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)+K(n%, 4,1) SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)+K(n%,4,2)SI 
CALL Projection (Xoa%, Yoa%, Dx, Dy, Dz) SI 
CALL Move& (RastPort&,Xua%, Yua%) f 
CALL Draws (RastPort&,Xoa%, Yoa%) 1 
D=Pm2/NumberSegmentsSI 
WHILE w<K(n%,5, 1)SI 
w = w+Df 
IF w>K(n%,5,l) THENSI 

w=K(n%,5,l)fl 
END IFf 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w)SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)SI 
CALL Projection (Xu%, Yu%, Dx, Dy, Dz) SI 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0) *SIN (w) +K (n%, 4 , 0) SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l) *SIN (w) +K (n%, 4 , 1 ) SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2) *SIN (w) +K (n%, 4 , 2) SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Move& (RastPortS, Xua%, Yua%) SI 
CALL Draws (RastPortS, Xu%, Yu%) SI 
CALL Draws (RastPortS, Xp%, Yp%) SI 
CALL Draws (RastPortS, Xoa%, Yoa%) SI 
Xua%=Xu%SI 
Yua%=Yu%SI 
Xoa%=Xp%SI 
Yoa%=Yp%SI 
WENDS! 
RETURNSI 
'SI 
DrawCone:SI 

CALL 
Projection(xl%,yl%,K(n%,l,0)+K(n%,4,0) , K (n%, 1 , 1 ) +K (n%, 4, 1) , K (n% 
l,2)+K(n%,4,2))SI 

CALL 
Projection (Xp%,Yp%,K(n%, 1, 0) +K (n%, 2, 0) , K (n%, 1 , 1 ) +K (n%, 2, 1) , K (n% 
l,2)+K(n%,2,2))SI 

CALL Moves (RastPortS, Xp%,Yp%) SI 

D=Pm2/NumberSegmentsSI 

FOR w=D TO Pm2+D/2 STEP DSI 

Dx=K (n%, 1, 0) +K (n%, 2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)1 
CALL Pro jection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Draws (RastPortS, Xp%,Yp%) SI 
CALL Moves (RastPortS, xl%,yl%) SI 
CALL Draws (RastPortS, Xp%,Yp%) SI 
NEXT wSI 
RETURNSI 
'SI 
DrawEllipsoidrSI 

D=Pm2/NumberSegmentsSI 

FOR wl=-Pd2+D TO Pd2-D/2 STEP DSI 

Dx=K(n%,l,0)+K(n%,2,0)*COS(wl)+K(n%, 4,0) *SIN(wl)SI 
Dy=K(n%,l,l)+K(n%,2,l)*COS(wl)+K(n%,4,l)*SIN(wl)SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(wl)+K(n%,4,2)*SIN(wl)SI 
CALL Pro jection(Xp%, Yp%, Dx,Dy, Dz) SI 



70 



Abacus 3.1 Wire Models 



CALL Moves (RastPort&,Xp%,Yp%) SI 
FOR w2=D TO Pm2+D/2 STEP Df 

Dx=K(n%,l,0)+K(n%,2,0)*COS(wl)*COS(w2)+K(n%,3,0)*COS(wl)*SIN(w2) 
+K(n%,4,0)*SIN(wl)fl 

Dy=K (n%, 1, 1 ) +K (n%, 2, 1 ) *COS (wl) *COS (w2 ) +K (n%, 3, 1 ) *COS (wl) *SIN (w2) 
+K(n%,4,l)*SIN(wl)S[ 

Dz=K(n%,l,2)+K(n%,2,2)*COS(wl)*COS(w2)+K(n%,3,2)*COS(wl)*SIN(w2) 
+K(n%,4,2)*SIN(wl)1 

CALL Project ion (Xp%, Yp%, Dx, Dy, Dz) 1 
CALL Draws (RastPort&,Xp%,Yp%) SI 
NEXT w21 
NEXT wl! 
FOR wl=-Pd2+D TO Pd2-D/2 STEP Dfl 

Dx=K(n%,l,0)+K(n%,2,0)*COS(wl)+K(n%,3,0) *SIN(wl)5 
Dy-K (n%, 1 , 1 ) +K (n%, 2, 1 ) *COS (wl ) +K (n%, 3, 1) *SIN (wl ) <& 
Dz=K(n%,l,2)+K(n%,2,2)*COS(wl)+K(n%,3,2)*SIN(wl)fl 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz ) 5 
CALL MoveS(RastPort&,Xp%,Yp%)SI 
FOR w2=D TO Pm2+D/2 STEP Dfl 

Dx=K (n%, 1, 0) +K (n%, 2, 0) *COS (wl) *COS (w2) +K (n%, 4, 0) *COS (wl) *SIN (w2) 
+K(n%,3,0)*SIN(wl)$ 

Dy=K (n%,l,l)+K(n%, 2, 1) *COS (wl) *COS (w2) +K (n%, 4,l)*COS (wl)*SIN(w2) 
+K(n%,3,l)*SIN(wl)5 

Dz=K(n%,l,2)+K(n%,2,2)*COS(wl)*COS(w2)+K(n%,4,2)*COS(wl)*SIN(w2) 
+K(n%,3,2)*SIN(wl)S[ 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) f 
CALL Draws (RastPortS, Xp%, Yp%) <J[ 
NEXT w21 
NEXT wlfl 
RETURNS 



Now for a word about circle presentation. The routines dealing with 
circles (almost everything except DrawPlane, DrawRectangle, 
and DrawTriangle) calculate the circle points in the same way: The 
segment points of the circle periphery are calculated depending on an 
angle. The more segment points, the rounder the circle. 

The rounder the circle, the longer the computation time involved. We 
have limited the number of segment points of a circle to save time. 
When the shadow routines are called we will get completely round 
circles. The variable Number Segments corresponds to the roundness 
of a circle: 



71 



3. The Tracer Program 



Amiga 3D Graphic Programming 



Number of segments 
4 




Figure 3.18 



Back to object and surface presentation: The abovementioned Draw... 
routines are individul subroutines. What calls the individual routines? 
The following routine jumps to the corresponding Draw... routine 
with the help of K(n%,0,0): 

DrawAllifl 

' Draw routine for calling each figured 
FOR n%=l TO NumberKl 
IF K(n%,0,0)=Q THENi 

GOSUB DrawPlaneSI 
END IFfl 
IF K(n%,0,0)=l THENfl 

GOSUB DrawTriangleSI 
END IF<I 
IF K(n%,0,0)=2 THENfl 

GOSUB DrawRectanglel 
END IFfl 
IF K(n%, 0,0)=3 THEN1 

GOSUB DrawCircleSI 
END IF1 
IF K ( n% , ; ) = 4 THEN1 

GOSUB DrawCircleSectorSI 
END IF1 
IF K(n%, 0,0) =5 THEN^I 

GOSUB DrawCircleRingfl 
END IFSl 
IF K(n%,0,0)=10 THEN5 

GOSUB DrawSpherel 
END IF SI 
IF K(n%,0, 0)=20 THENf 

GOSUB DrawCylinder^I 
END IFSl 
IF K(n%,Q, 0)=21 THENSI 

GOSUB DrawCylinderSegm^l 
END IF<5I 
IF K(n%,0, 0)=22 THEN$ 

GOSUB DrawConeSI 
END IF1 
IF K(n%, 0,0) =24 THEN5 

GOSUB DrawEliipsoidSI 
END IF1 
NEXT n%? 
RETURN^ 



7 2 



Abacus 3.1 Wire Models 



The DrawNew routine ensures that the screen is cleared before any 
objects are displayed, and takes all of the necessary steps before the call 
(activates the screen, waits for a key and returns to the user screen). 

If none of the parameters (Projection point, Main point, etc.) 
are changed in the meantime, the picture is not refreshed. 

Our tracer program allows you to choose backgrounds for your 
drawings. Should you choose a new background for the picture because 
the original background color is too distracting, DrawNew provides for 
this by clearing the background. The picture then appears over the 
selected background: 

DrawNew: SI 

IF (Hg = False) AND (Newone! - True) THEN • no Backgrounds 

CALL SetRast& (RastPort&, 0) ' but new drawingSI 

END IF ' => clear screenSI 

SI 

CALL Scron SI 
SI 

IF (Newone! = True) OR (Hg = True) THEN ' Background and 
New drawingSI 

GOSUB DeleteMenuSI 

RetRastS = RastPortS ' reserve RastPort SI 

RastPort& = WINDOW (8) ' In Window-RastPort 

(GIMMEZERO Window!) SI 

CALL SetAPen&(RastPort&,l) ' the new ScreensSI 
GOSUB DrawAll • draw (because of Clipping) SI 

RastPortS = RetRast&SI 
BEEPSI 
END IFSl 
SI 

IF WaitFlg! = True THEN ' wait for mouse or key 

pressSI 

GOSUB Pause SI 

CALL ScroffSI 
END IFSI 
SI 

IF (Newone! = True) OR (Hg = True) THENSI 

Newone! = False ' Redraw picture SI 

Hg = False ' and "paint over"SI 

GOSUB MakeMenu ■ background SI 

END IFSI 
RETURNSI 



73 



3. The Tracer Program Amiga 3D Graphic Programming 



3.2 The Editor 



3.2.1 Why an Editor? 



Our goal is to design a program that calculates any picture that is made 
up of simple objects and display it in 3D. The previous section 
described which objects and which data are needed to do this. It is also 
known that this data is stored in the arrays K ! and MAT ! . Now, how do 
we insert the data for our picture into this array? Many different 
methods are available. 

One solution would be to manually calculate all of the data and enter it 
as program lines, then read the data with a corresponding routine. This 
is the easiest to implement, but the hardest to test. The advantage: you 
save a lot of time in program development. The disadvantage: the user 
must have the finished picture in mind and enter it by hand, and then he 
has no control over whether the data complies with his image. 

It is also possibile to save the calculated numbers into a separate file 
with the help of a word processor. The program then reads these lines 
into memory. The disadvantage shown above applies to this case as 
well. 

It would be better to enter the values into the computer and display 
these values graphically. This is done using a simple menu driven 
program which displays the data input as three pictures, and lets you 
make corrections. The next section shows how to do this in BASIC. 



74 



Abacus 



3.2 The Editor 



3.2.2 



The Tasks Required of the Editor 



The graphic 
output 



Once the larger programming objective is established, all of the detail 
work is before us. All of the desired values and features of this editor 
must also be determined. For this we divide the editor into its 
individual, logical, and functional sections, called modules. The main 
task of the editor is to read in numerical data. We must add input and 
output procedures for this. Since we want this data presented both as 
numbers and as a wire model, the corresponding procedures must be 
developed. Some additional functions are used; they are not necessary, 
but make the program more user friendly. The individual modules are 
explained in the following sections. 

The graphic presentation cannot be displayed as a finished three 
dimensonal graphic complete with light, shadows, hidden lines, or 
reflections. This would take far too much computation time. On the 
other hand, displaying the graphic as a wire model in perspective in the 
editor is possible but not to our advantage. The details would be barely 
recognizable and perspective would be distorted. We reserve both the 
wire model in perspective and the final shadowed graphic for our ray 
tracing program. 



The method that shows the user input fastest and easiest is the 
projection of bodies from the three main views. The object appears in 
front, side, and top views, like a standard technical drawing. The front 
view is equivalent to the xz plane, the side view of the projection is 
equivalent to the yz plane, and the top view is equivalent to the 
projection of the xy plane. The illustration below shows perspective 
(1), top (2), side (3) and front (4) views of a simple 3D house: 



Figure 3.19 






75 



3. The Tracer Program 



Amiga 3D Graphic Programming 



These three views are displayed in three windows at the same time. 
Because the screen doesn't divide very well into three sections, we 
divide it into quarters and have one section for data entry and text 
output. The windows are very small, but the user can enlarge and move 
them. It must also be possible to move and enlarge the section where 
the individual window is displayed so that large objects can be entered 
and that details can be recognized. The following example should make 
this clear. 



Figure 3.20 




The rectangle surrounding the lower house represents the window; the 
lower house is visible, the house above remains hidden. By moving the 
border in the Y direction, the second house becomes visible: 



y a 



Figure 3.21 




76 



Abacus 



3.2 The Editor 



The section is made clear by examining the position of the upper left 
hand corner. In the first case this corner is (0,28,0) and in the second 
case it is (0,42,0). 

Data input A program should be designed so that the inexperienced user can easily 

and output use it, recognize incorrect input, and correct data already entered. The 

interface between the user and the program provides the use of menus 

on the Amiga. 

Direct input of data is also required. In our editor program you can, for 
example, enter data at the following text: 

Body : 1 Sphere 

visible :_ Material :_ 

M : , , 

r : 

This input could achieved using the INPUT statement. We don't advise 
this because you have no control over the entered characters. Writing 
your own routine that gives you control of the entered characters is a 
better solution. Besides correcting data, manipulating the entered data in 
our program would be very helpful. By manipulation we mean rotating, 
moving, enlarging and copying an object. Naturally old data sets must 
be either redisplayed or deleted. Adding the mouse as an input device 
eases the use of the editor. The mouse makes it possible to simply 
click on the necessary coordinates. You don't have to manually 
compute them and enter them in the computer through the keyboard. 

Additional What most professional Amiga applications have in common is the 

features ability to use gadgets (objects on the screen that can be selected with 

the mouse, such as sliders, text gadgets, etc.). Programming gadgets in 

AmigaBASIC can be complicated, but it makes the program easier for 

the average person to use. 

One final point: The editor must make it easy to change a graphic made 
of many objects. If the user has a graphic made of 253 different objects, 
and object 253 is incorrect, should the user re-enter all 253 objects? No. 
We added a function that lets the user view each object, change it, and 
save it for later recall. 

The abovementioned features have almost completely described our 
editor program; only the realization is missing. One possibility for 
programming such an editor is listed completely in the appendices. The 
following sections describes the most important routines of this editor. 
From these routines we can create a relatively simple and fast editor for 
creating 3D objects. 

The optional disk for this book contains the sample editor program that 
is listed in the appendices. Section 4.1 of this book contains a brief 
usage guide for this editor. We recommend that you look at this 
program to get a feel of what is in store in the next pages. Before you 
put the book aside to get to work on your Amiga, we should offer you 



77 



3. The Tracer Program 



Amiga 3D Graphic Programming 



the following tip in case you have difficulties with the abovementioned 
projects. The optional disk has a data file named House . You must 
execute the following procedure to view this file from the optional 
disk: 



9 

10 



Load AmigaBASIC 
enter CLEAR, 120000 
enter LOAD "editor .bas" 
start the program (with RUN) 
wait a few seconds-be patient 
select "Load List" from the "Disk" 
type house and press RETURN 
press CTRL-R 
wait some more 
. look around (e.g., section) 



3.2.3 



Individual Components of the Editor 



The following sections describe each module, refine them, and show 
them in BASIC program form. Then the long-range goals and 
associated problems are presented, and the simplest procedures solved. 
For example, the input module includes a procedure for reading the 
keyboard. This procedure comes from a normal string input routine, 
from which the input procedure for a real number is supported which is 
finally called from the procedure to read a vector. This principle of 
development allows the creation of more complex algorithms in the 
rest of the chapter. 



3.2.3.1 



The Input 



When a number is entered in a program, an input error may occur if 
M onehundred23", M la23" or something similar is entered. The input 
routine should make sure that the only active key is the one the user 
pressed. The <Delete>, <Backspace>, <Cursor left>, <Cursor right> 
and <Return> keys function as usual. 

The INPUT routine of BASIC is unusable here. The procedure used 
instead of the INPUT routine is called get string. It reads a variable 
length string from a certain place on the screen and places this string in 
a window. The character string can be scrolled left and right within this 
window. 

To read a character string there must be a routine that sets the cursor on 
the screen, waits for a keypress, then erases the cursor. To display the 



78 



Abacus 3.2 The Editor 



cursor at a certain point on the screen, the character width and height 
must be known. This is dependent on the chosen character set. The 
important information for this is in the RastPort data structure. To 
explain what this has to do with the RastPort data structure and how 
it is constructed would be outside the realm of this book. It is 
important for our purposes that the character height and width can be 
found as follows: 

rp&=WINDOW{8) 'take the pointer from RASTPORT 
cw% = PEEKW(rp&+-60) 'character width 
ch%=PEEKW(rp&^58) 'character height 

Now to display the cursor so that the characters under the cursor remain 
readable, the screen section must be inverted. This is done simply with 
SETDRMD, a function that is found in the graphics . library and 
linked to our program with (our disk name is Tracer and the bmap files 
are located in the libs directory): 

LIBRARY "Tracer: /graphics. library" 

After this preparation the routine is simply: 

SUB setcursor(z,s) STATIC^ 

'TASK : set cursor at specified position^ 

' PARAMETER :=>z lineal 

1 s column 'ff 

SHARED cw%,ch%SI 

CALL setdrmds (WINDOW (8) ,2)1 

LINE (s*cw%-cw%,z*ch%-ch%-l)Ms*cw%,z*ch%-l),3,bfI 

CALL set drmd& (WINDOW (8) , 1)1 
END SUB fB 

When setcursor is called twice with the same parameters, the 
cursor is erased again and the characters under it are presented normally: 

SUB getkey(a$,z,s)STATTCf 

'TASK :Read one character inl 

' PARAMETER: =>z linefl 

1 s column*! 

' <=a$ pressed keySI 

CALL setcursor (z, s) SI 

a$=""f 

WHILE a$=""l 
a$=INKEY$1 

WEND1 

CALL setcursor (z, s) 1 
END SUB1 

These two procedures are used in the procedure get string. This 
routine requires the old contents of the string, the keypress, the 
allowable characters, window position, and window length. Passing the 
routine the old string contents allows changes to an existing character 
string without re-entering the string's contents. 

SUB getstring (old$, a$, z$, z, s, inplen) STATICf 



79 



3. The Tracer Program Amiga 3D Graphic Programming 



TASK : Reads two strings which can be edited from the inputs 
line using cursor left /right, backspace and delete. SI 
In addition the string scrolls when the input ! 
extends past the screen line ! 
PARAMETER :=>old$ old value of string to be read! 
a$ key pressed ! 
z$ valid characters! 
z line! 
s column! 

inplen Lenght of inout window*! 
<=old$ specified string! 
IF inplen =1 THEN 'if only one char entered? => no Return! 
ald$=a$! 
WHILE INSTR(z$, old$)=0! 

CALL getkey(old$,z,s)! 
WEND! 

LOCATE z,s! 
PRINT oid$! 
ELSE! 

i=l 'points to current string position! 
position=l 'points to current screen position! 
WHILE ASC(a$)><13! 

IF INSTR(z$,a$)><0 THEN 'valid character?! 

old$=LEFT$ (old$ / i-1) +a$+RIGHT$ (old$, LEN (old$) -i + 1) ! 

i=i+l! 

posit ion=position+l! 

IF position>inplen THEN! 

position=inplen ! 
END IF ! 
ELSE ! 

IF ASC(a$)=30 AND i<=LEN(old$) THEN 'Cursor right?! 
i=i+l! 

posit ion=position+15 
IF position>inplen THEN! 

position=inplen ! 
END IF ! 
ELSE! 

IF ASC(a$)=31 AND i>l THEN 'Cursor left?! 
i=i-l! 

position^position-1! 
IF position=0 THEN! 

position=l! 
END IF ! 
ELSE! 

IF ASC(a$)=127 AND i<=LEN(old$) THEN 'delete ?! 
old$=LEFT$ (old$, i-1) +RIGHT$ (old$,LEN (old$) -i) ! 
ELSE! 

IF ASC(a$)-8 AND i>l THEN 'Backspace ?! 
i=i-11 

position=position-l! 
IF position=0 THEN! 

position=l! 
END IF! 

old$=LEFT$ (old$, i-1) +RIGHT$ (old$, LEN (old$) -i) ! 
END IF! 
END IF! 
END IF! 
END IF! 
END IF! 
LOCATE z,s! 

PRINT MID$ (old$+" ", i-position+1, inplen ) 'String 
output! 



80 



Abacus 



3.2 The Editor 



CALL get key (a$, z, s+position-1) "get next key SI 
WEND SI 
END IFSl 
IF iXposition THENSI 

CALL putstring(old$,z,s, inplen ) SI 
END IF SI 
END SUM 

Next we examine if the length is equal to one or not. If so, it waits for 
a valid key and returns this, and in the other case the characters are read 
until the user presses the <Return> key. Each character is checked to 
see if one of the following five cases occurs: 

1 .) Valid characters (in z $), then INSTR(z $ , a $) is unequal to zero 
and the characters are inserted in the corresponding place in 
old$. Then i and position must be increased to ine 

2.) <Cursor right>, then i and position are increased by one 

3.) <Cursor left>, i and position are lowered by one. I is 
important to make sure that these two varaibles do not take on 
an invalid value 

4.) <Delete>, here the ith characters are removed from old$ 

5.) <Backspace>, a combination of <Cursor left> and <Delete> 

The entire valid area of the string is displayed and the routine waits for 
the next key. When the user presses <Return>, the length of the 
characters is given. The put string routine (described later in this 
section ) is used. 

The following routine simplifies the input of integers and real values: 

SUB getreal (i! ,a$, z, s, inplen ,unt!,ob!) STATIC SI 
TASK :Read in real valued 
PARAMETER: =>i ! old valuel 

a$ pressed keySI 
z line SI 
s column SI 

inplen length of input lineSI 
unt! upper limits 
ob! lower limits 
<=i! specified valued 
CALL conrealstr (i : , j$)SI 
loopl: SI 
i$=j$1 

CALL getstring(i$,a$, "1234567890- . ", z, s, inplen ) SI 
j$=i$SI 

CALL constrreal (i$, i ! ) SI 
IF i$ = "" OR i!<unt! OR i!>ob! THENSI 
a$ = " "f 
GOTO loopl SI 
END IFSI 
END SUBSI 



81 



3. The Tracer Program Amiga 3D Graphic Programming 



The routine for reading an integer value is identical to the above 
routine, the only difference appearing in the call of get string ("." is 
allowed in getreai but not in getint). The statement of the value 
range is necessary for the parameters already known, as well as the 
upper and lower limits of all valid numbers (unt ! ,ob ! ). Both 
procedures use two routines that have not been mentioned till now: the 
conversion routines conrealstr and constrreal: 

SUB conrealstr(i!,i$) STATIC! 
'TASK : convert real value into string! 
' rounded to 3 decimal places! 

' PARAMETER : =>i ! the real value! 
' <=i$ the string! 

i$=STR$(i! )! 

j!=FIX(100Q!*.i !+-.5*SGN(i! ) ) /1Q00! 'round! 
i$=STR$(j!)! 
IF ABS(j!)>0 AND ABS ( j ! ) <1 THEN 'if 0<j!<l inserted! 

i$=MID$(i$,l,l)+"0"+MID$(i$,2,LEN(i$) )! 
END IF! 
IF j!>=0 THEN 'if 0<=j! truncate first place! 

i$=RIGHT$(i$,LEN(i$)-l)! 
END IF! 
END SUB! 
! 

SUB constrreal (i$,i!) STATIC! 
'TASK :convert string into real value! 
' PARAMETER :=>i$ the string! 
' <=i ! the real value! 

' i$ if conversion error i$=""! 

i!=VAL(i$)! 
IF i!>=0 THEN! 

IF i !>0 AND i!<l THEN! 

i$=" "+RIGHT$(i$,LEN(i$)-l) 'insert space and cutoff 0! 
ELSE ! 

i$=" "+i$ 'insert space! 
END IF! 
END IF! 

j!=i!-FIX(i!*1000!)/1000! 'round ! 
IF i$XSTR$(i!) OR j!><0 THEN 'Error ?! 

i$=""1 
END IF ! 
END SUB! 



Notice that real values in both procedures have only three places alter 
the decimal point, and the values whose sums lie between zero and one 
have a preceding zero. When the input does not satisfy these 
requirements, the constrreal routine makes the empty character 
string the output value for i$, as the result of incorrect input. The 
restriction to three places after the decimal point is necessary because 
exact input values change minutely when calculating the graphic later. 

Besides character strings, integer and real numbers in our program need 
vectors as input. It is practical to write individual input procedures for 
these objects. A vector is presented by three real numbers separated by 
commas. We use the conversion routines (con3realstr and 
constr3real) in the input procedure, and for the first time the 



82 



Abacus 



3.2 The Editor 



mouse position emerges, because mouse input is allowed. This only 
works when reading room coordinate vectors and not angle vectors. An 
additional parameter tells the procedure whether mouse input is allowed 
or not. The mouse position is stored in the global variables called 
mox ! , moy ! and moz ! . To let the procedure know that the keyboard 
input doesn't count, we press <Return> and no other keys. And now 
the routine: 



SUB get3real (il ! , i2 ! , i3 ! , a$, z, s, inplen , unt !, ob !, modus) 
STATIC! 
TASK :read 3 Real values in! 
PARAMETER :=>il! , i2! , i3! old value! 
a$ key pressed! 
z line! 
s column! 

inplen Lenght of input line! 
unt! lower limit! 
ob! upper limit! 
modus if=0 no mouse entry! 

if=-l mouse input (position vector)! 
if>0 mouse inout (Difference vector)! 
<=il ! , i2 ! , i3! specified value! 
SHARED mox ! , moy ! , moz ! , k ! ( ) ! 
CALL con3realstr(il! , i2 ! , i3 ! , j$) ! 
IF a$="" THEN! 

CALL getkey (a$,z, s)! 
END IF ! 

IF ASC(a$)=13 AND modusxO THEN! 
IF modus=-l THEN! 
il!=mox!! 
i2!=moy!! 
i3!=moz!! 
ELSE! 

il!=mox!-k! (modus, 1,0)! 
i2!=moy!-k! (modus, 1,1)! 
i3!=moz!-k! (modus, 1,2)! 
END IF! 

CALL put3real (il ! , i2 ! , i3 ! , z, s,26)! 
ELSE! 
loop2:! 

i$=j$ ! 

CALL getstring(i$,a$,"1234567890-.,",z,s, inplen )! 
j$=i$! 

CALL constr3real (i$, il ! , i2 ! , i3 ! ) ! 

IF i$= ,,n OR il!<unt! OR i2!<unt! OR i3!<unt! OR il!>ob! OR 
i2!>ob! OR i3!>ob! THEN! 
a$=" "! 
GOTO loop2! 
END IF! 
END IF! 
END SUB ! 



The single addition to this routine is the second IF check where the 
array k ! emerges for the first time. First the program checks for an 
allowable mouse input. If so, the modus index selects from the mouse 
vector, or from the difference vector between the mouse vector and the 
reference vector of the object. 



83 



3. The Tracer Program Amiga 3D Graphic Programming 



As before, we use the conversion routines (con3realstr and 
constr3real): 

SUB constr3 real (i$,il! ,121,13!) STATIC! 

•TASK : convert one string into 3 real values! 

• PARAMETER: =>i$ the string! 

<=il!,i2!,i3! the real values! 
1 i$ if conversion error i$= lin ! 

Problem=0! 
i$=i$+","! 
FOR i=l TO 3! 

comma=INSTR(i$, ", ") "Mark comma position! 
IF comma<=l THEN 'Problem ?! 

Problem^l! 
ELSE! 

a$=MID$ (i$,l,comma-l) "truncate string to be converted! 
i$=RIGHT$ (i$,LEN (i$) -comma) 'mark the rest! 
CALL constrreal (a$, i! (i) ) 'convert! 
IF a$="" THEN 'Problem ?! 

Problem=l! 
END IF ! 
END IF! 
NEXT 11 
IF Problem=l THEN! 

1$="" ! 
ELSE! 
i$=" "! 
il!=i! (1)1 
i2!=i! (2)! 
i3!=i! (3)! 
END IF! 
END SUB 1 



SUB con3realstr (il! , i2 ! ,i3! , i$) STATIC! 

'TASK : convert 3 real values into vector string! 

• PARAMETER: =>il!, 121,13! the 3 Real values! 

' <=i$ the string! 

CALL conrealstr (il! f il$)! 

CALL conrealstr (i2!,i2$)! 

CALL conrealstr (i3!,i3$)! 

i$=il$+", "+12$+", "+i3$! 
END SUB! 



Both routines support the conversion procedures and operate in the 
same way. The constr3real procedure is a little complicated 
because the beginning position of the coordinates in the character string 
must be determined by using the INSTR function. After all this 
preparation, we want to program a menu for our editor. As an example, 
we use the menu for a circle section because it uses all of input 
procedures discussed so far. Next the location and length of the screen 
must be determined. These positions are arbitrary. To simplify the 
following program, these values are stored in an array (tabs). 

A requirement for our menu was that a correction to entered data could 
be made at any time. This should be done with the <Cursor up> and 
<Cursor down> keys. <Cursor up> moves you to the previous cursor 



84 



Abacus 3.2 The Editor 



position and <Cursor down> moves you to the next position. So that 
the procedure knows which input follows, a number variable (nr) is 
used, which is in a certain range (0 <= nr <= number of input 
positions). Besides the object data, additional information is needed 
concerning whether the objects in the projection window should be 
visible or not. This boolean value is stored in k ! (ptr,5,2) where pt r 
points to the given object and the type is entered in k ! (pt r,0 ,0). 

SUB getcrarc(ptr) STATIC5 

SHARED k! () ,tabs() ,min! ,max! , grad ! , rad!5 

tabs(0,0)=25 

tabs (1,0) =25 

tabs (2,0) =31 

tabs (3,0) =45 

tabs (4,0) =51 

tabs (5,0) = 65 

tabs (6,0) =65 

tabs(7,0)=75 

tabs(8,0)=75 

tabs (0,1) =105 

tabs(l,l)=225 

tabs(2,l)=45 

tabs(3,l)=45 

tabs(4,l)=45 

tabs (5,1) =45 

tabs (6,1) =165 

tabs (7,1) =45 

tabs (8,1) =165 

nr=05 

WHILE nr<=85 

CALL getkey(a$,tabs (nr, 0) ,tabs(nr,l) )5 
IF ASC(a$)=28 THEN5 
IF nr>0 THEN5 

nr=nr-15 
END IF 5 
ELSE 5 

IF ASC(a$)=29 THEN5 

nr=nr+15 
ELSE5 

IF nr=0 THEN5 

CALL getstring(b$,a$, "yn", tabs (nr, 0) , tabs (nr, 1) , 1) 5 
IF b$= n y"THEN5 

k! (ptr,5,2)=15 
ELSE 5 

k! (ptr,5,2)=05 
END IF5 
END IF5 
IF nr=l THEN5 
CALL 
getint(k! (ptr, 0, 2) , a$, tabs (nr, 0) , tabs (nr, 1) ,5,1! , max ! ) 5 
END IF 5 
IF nr=2 THEN5 
CALL 
get 3 real (k! (ptr, 1,0) ,k! (ptr, 1, 1) ,k! (ptr, 1,2) , a$, tabs (nr, 0) ,tabs ( 
nr, 1) ,26,min!,max!,-l)5 
END IF5 
IF nr=3 THEN5 
CALL 
get3real (k! (ptr,2,0),k! (ptr, 2,1) ,k! (ptr, 2,2) , a$, tabs (nr, 0) , tabs ( 
nr, 1) , 26,min! ,max! , ptr) 5 



85 



3. The Tracer Program 



Amiga 3D Graphic Programming 



END IF! 
IF nr=4 THEM 
CALL 
get3real(k! (ptr, 3, 0) , k! (ptr, 3,l),k! (ptr, 3, 2) , a$, tabs (nr, 0) ,tabs( 
nr,l) , 26,min0! , max!, ptr)! 
END IF! 
IF nr=5 THEN! 

k!=grad!*k! (ptr, 5,0)! 

CALL get real (k! , a$,tabs(nr, 0) ,tabs(nr,l) , 8,min! , max! )! 
k! (ptr, 5,0)=rad!*k!! 
END IF ! 
IF nr=6 THEN! 

k!=grad!*k! (ptr, 5, 1)5 

CALL getreal (k! ,a$,tabs(nr, 0) , tabs (nr,l) , 8,min! , max ! ) ! 
k! (ptr,5,l)=rad!*k!! 
END IF ! 
IF nr=7 THEN! 
CALL 
getreal (k! (ptr, 4, 0) , a$, tabs (nr, 0) , tabs (nr, 1) , 8,0! ,1!)! 
END IF ! 
IF nr=8 THEN! 
CALL 
getreal (k! (ptr, 4, 1) , a$, tabs (nr, 0) , tabs (nr, 1) ,8,0! ,1!) SI 
END IF ! 
nr=nr+l! 
END IF! 
END IF! 
WEND ! 
END SUB ! 



As you see, implementation in BASIC is easy with this procedure. The 
read procedure for the rest of the objects uses similar programming, and 
should present no difficulty. If you have problems you should look at 
the finished editor in the appendices and on the optional disk. 



3.2.3.2 



The Output 



The output routines display the value of a variable, with a certain 
length, on the screen. The simplest case is the output of a character 
string that uses the MID$ function to extract the correct section. 



SUB putstring(s$,z,s,inplen ) STATIC! 
TASK : output of a string of a certain length! 
PARAMETER: =>s$ the string! 
z line! 
s column! 

inplen Lenght of output window! 
LOCATE z,s 'clear specified range! 

PRINT SPACE$ (inplen )! 

LOCATE z,s 'display the string! 

PRINT MID$(s$,l, inplen )! 
END SUB! 



86 



Abacus 3.2 The Editor 



As with the input procedures, the operations for real values and vectors 
can be simplified with this put string routine. First the values must 
be converted into strings using the conversion functions, and then 
displayed with the put string routine: 

SUB putreal (i ! , z, s, inplen ) STATIC*! 

'TASK : Display real value of predetermined length! 

1 PARAMETER :=>i! the real valued 

' z line! 

' s column! 

1 inplen Length of output window*]! 

CALL conrealstr ( i. ! , s$)! 

CALL put st r i ng (s$, z, s, inplen )! 
END SIM 

! 
SUB put3real (il!,i2!, i3!,z,s, inplen ) STATIC*! 
'TASK : display 3 Real values of certain length*! 
'PARAMETER:^ ill, 12! ,i3! the real values! 

z line! 
1 s column! 

' inplen Length of the output window! 

CALL con3realstr(il! , i2! , i3 ! , i$) ! 

CALL putstring(i$, z, s, inplen )! 
END SUB! 
! 

Now all we need is the display procedure for object data. Unlike an 
input, where a separate routine must be constructed for each object, it 
can all be done in one output procedure: 

SUB showelem(ptr) STATIC! 
'TASK :data output of element ptr! 
' PARAMETER :=>pt.r pointer to the specified element! 
SHARED k! () , typ$ () , empty$, grad! , rad!! 
LOCATE 1,1! 
FOR 1----1 TO 7! 

PRINT empty $! 
NEXT i! 
LOCATE 1,1! 
PRINT "Body : "! 
CALL putreal(ptr*l!,l,8,5)! 
typ=INT(k! (ptr, 0,0))! 
IF ptr><0 THEN! 
LOCATE 1,14! 
PRINT typ$(typ)! 
LOCATE 2, 1! 
PRINT "visible :";! 
IF k! (ptr, 5, 2)----0 THEN! 

PRINT "n"! 
ELSE ! 

PRINT "y"! 
END IF! 
LOCATE 2, 13! 
PRINT "Material:"! 
CALL putreal (k! (ptr, 0,2) ,2,22,5)! 
IF typ=10 THEN! 
LOCATE 3,1! 
PRINT "M :"! 
PRINT "r :"! 
CALL put 3 real (k! (ptr,l,0),k! (ptr, 1,1) ,k! (pt r , 1 , 2 ) , 3, 4 , 26) ! 



87 



3. The Tracer Program Amiga 3D Graphic Programming 



CALL put real (k! (ptr,2,0) ,4,4,8)5 

ELSE! 

LOCATE 3,1 5 
PRINT "M :"5 
PRINT "A :"5 
PRINT "B :"5 

CALL put3real(k! (ptr,l,0),k! (ptr, 1,1) ,k ! (ptr, 1,2) , 3, 4, 26) 1 
CALL put3real (k! (ptr,2,0),k! {ptr, 2,1) ,k! (ptr, 2, 2) , 4, 4, 26) 5 
CALL put3real(k! (ptr f 3,0),k! (ptr, 3,1) ,k! (ptr, 3, 2) , 5, 4, 26) 1 
IF typ>=4 THEN5 
IF typ>=20 THEN5 
LOCATE 6,11 
PRINT "C : "5 
CALL 
put3real (k ! (ptr, 4,0),k! (ptr, 4,1) ,k! (ptr, 4,2) , 6, 4, 26) SI 
IF typ=21 THEN5 
LOCATE 7,1^ 
PRINT "sw:"5 
LOCATE 7,135 
PRINT "ew:"5 

CALL put real (grad!*k! (ptr, 5, 0) , 7,4, 8)5 
CALL putreal(grad!*k! (ptr, 5, 1) , 7, 16, 8) 5 
•END IF5 
ELSE5 

LOCATE 6,15 
PRINT "sw:"5 
LOCATE 6,135 
PRINT "ew:"1 

CALL putreal (grad!*k! (ptr, 5,0) ,6,4,8)5 
CALL putreal (grad!*k! (ptr, 5, 1) , 6, 16, 8) 5 
IF typ-5 THEN5 
LOCATE 7,15 
PRINT "ri:"5 
LOCATE 7,135 
PRINT "ra:"5 

CALL putreal (k ! (ptr, 4, 0) , 7, 4, 8) 5 
CALL putreal ( k ! (pt r , 4 , 1 ) , 7 , 1 6 , 8 ) 5 
END IF5 
END IF5 
END IF5 
END IF5 
END IF5 
END SUB5 
5 

This procedure is easy, but it must be remembered that the CLS 
statement, used for erasing the screen in BASIC, cannot be used in this 
program because a section of the screen must remain intact. To delete 
this section, every line is overwritten with a certain number of empty 
fields stored in empty$. Another critical point is the array typ$ into 
which the object names for the individual type numbers are stored. The 
array typ$ is installed as follows: 

typ$ (0)="Plane" 'arrange by type and name! 

typ$(l)="Triangle"5 

typ$ (2 ^"Parallelogram'^ 

typ$ (3)-"Circle u 5 

typ$ (4) ^"Circle segment"! 

typ$(5)="Arc"5 



88 



Abacus 3.2 The Editor 



typ$ (10)="Sphere"! 

typ$(20)="Cylinder"! 

typ$ (21) ="Cy Under segment" 

typ$(22)="Cone"! 

typ$ (24)="Spheroid" ! 



3.2.3.3 The Graphics 



The graphic commands used in this program should consider that each 
object must be displayed in three different windows. To complicate the 
implementation of this routine, you must add the enlargement factor 
and the chosen section. This isn't easy, because pixel width is less than 
pixel height on the Amiga. This can be evened out by making a 
correction factor for the X coordinates. You may have seen this 
phenomenon for yourself, but if not, try to display a square with an 
edge length of 100. When you use the following command, you may 
see a rectangle on the screen instead of a square: 

LINE (0,0) -(100,100) , ,b 

To calculate the correction factor you must measure the height of the 
rectangle and divide it by its length. This value should change in the 
program to correspond to your screen (the variable is called 
xcoorf ac ! and is in the init SUB program). 

The simplest graphic objects are points and lines. We use room 
coordinates in our program instead of screen coordinates. This means 
we must create our own procedures for these graphic objects. You'll 
need the coordinates of the point or line, the character color (colour), 
the statement of the section and the enlargement factor (factor ! ). 
The window function receives the data about the window display. 

SUB setpoint (x ! , y! ) STATIC*! 

'TASK : set point in current output window! 

'PARAMETER: =>x ! ,y! Point coordinated 

SHARED mx ! , my ! , mz ! , factor ! , xcorr f ac ! , colour! 
swindow=WINDOW ( 1 ) ! 
IF swindow=l THEN! 

LINE ((x!-mx!)*xcorrfac!*factor!, (my!-y! ) *f actor! )-( (x ! - 
mx! ) *xcorrfac!* factor! , (my !-y ! ) *factor! ) , colour! 
ELSE! 

IF swindow=2 THEN! 

LINE ((x!-mx!)*xcorrfac!*f actor!, (mz! -y! ) *f actor !)-( (x! - 
mx! ) *xcorrfac!*factor! , (mz !-y! ) * factor! ) , colour! 
ELSE! 

IF swindow-3 THEN! 

LINE ( (my !-x! ) *xcorrfac! *f actor ! , (mz ! -y ! ) * factor ! ) - 
( (my ! -x! ) *xcorrfac! *factor! , (mz ! -y ! ) *factor ! ) , colour! 
END IF! 
END IF! 



89 



3. The Tracer Program Amiga 3D Graphic Programming 



END IF? 
END SUB? 
? 

SUB drawline(x!,y!) STATIC? 

'TASK :draw line from last point to specified point? 
' PARAMETER :=>x!,y! Point coordinates? 

SHARED mx! , my! ,mz! , factor! , xcorrfac! , colour? 
swindow=WINDOW(l) ? 
IF swindow=l THEN? 

LINE - ( (x!-mx! ) *xcorrfac ! *factor ! , (my ! -y !) *f actor !), colour*! 
ELSE? 

IF swindow=2 THEN? 

LINE - ( (x ! -mx ! ) *xcorr f ac ! * factor ! , (mz ! - 
y! ) *factor! ) .colour? 
ELSE? 

IF swindow=3 THEN? 

LINE - ( (my !-x! ) *xcorrfac! * factor! , (mz ! - 
y ! ) * factor ! ) , colour? 
END IF? 
END IF? 
END IF? 
END SUB? 



Now comes the drawing routine for an ellipse. Let's think about how 
an ellipse can be constructed. 

We have used a method that uses the midpoint of the ellipse and two 
more vectors which span the ellipse, clearly establishing the ellipse. 
The ellipse begins by rotating the two vectors around the midpoint. 
When a full rotation is executed, all of the points of the ellipse are set. 

Because there are an infinite set of numbers between and 360, it is 
impossible for every angle of the ellipse points to be calculated. For 
every circle or ellipse we approach a certain number of lines 
(maxlines). The larger the number, the more accurately the ellipse 
appears, but the more computation time needed. This number should be 
chosen later in the program so the user has some control over the 
drawing speed. Arcs (partial ellipses) can be calculated as well as 
complete ellipses — start and end angles act as additional parameters: 

SUB drawellipse (ax ! , ay ! , bx ! , by ! ,mx ! , my ! , sw! , ew ! ) STATIC? 
TASK :draw ellipse in current output window? 
PARAMETER : =>ax ! , ay! , bx ! , by! span of ellipse? 
mx!,my! center point of ellipse? 
sw ! , ew ! the start angle and end angle? 
to be used? 
SHARED maxlines,pi2!? 
alpha !=sw!? 

numlines=ABS (sw! -ew! ) *maxlines/pi2 ! 'Compute number of lines? 
IF numlines=0 THEN? 

numlines=maxlines 'if sw!=ew!, draw full ellipse? 
beta! =pi2! /maxlines? 
ELSE ? 

beta!=ABS (sw! -ew! ) /numlines 'compute increment angle? 
END IF? 

x ! =ax ! *COS (alpha ! )+bx!*SIN (alpha !)+mx! 'compute start point? 
y ! -ay ! *COS (alpha ! ) +by ! *SIN (alpha ! ) +my ! ? 



90 



Abacus 



3.2 The Editor 



CALL setpoint {x! , y ! ) 'Start point outputs 
FOR i=l TO numlinesl 

alpha !=alpha !+beta! 'compute new angle! 

x! =ax! *COS (alpha! ) +bx! *SIN (alpha! ) +mx! 'compute new point 1 

y!=ay!*COS (alpha! ) +by ! *SIN (alpha ! )+my!1 

CALL drawline (x! , y ! ) 'draw line from old point to newf 
NEXT if 
END SUBf 

The beginning of this routine calculates the number of lines. When a 
full ellipse is displayed, this number is the maximum; when only a 
half ellipse is desired, this number is halved, and so on. When this 
number is set, the step value, which increases the angle from the start 
value to the end value, can be found. The actual rotation of the vectors 
uses both the sine and cosine functions. 

For an example of the above three routines, let's develop a display 
routine for a cone. This procedure should draw the cone in three 
windows then place the numeric output in the fourth window, which is 
used for text input and output. The base must be given first and then 
four lines drawn from this base to the cone peak. The beginning point 
of these lines runs through the base vectors: 



SUB drawcone(ptr) STATICl 
SHARED k! (),pi2!1 
mx!=k! (ptr, 1,0)1 
my!=k! (ptr, 1,1)1 
mz!=k! (ptr, 1,2)1 
ax!=k! (ptr, 2, 0)1 
ay!=k! (ptr, 2,1)5 
az!=k! (ptr, 2, 2)1 
bx!=k! (ptr, 3,0)1 
by!=k! (ptr, 3, 1)1 
bz!=k! (ptr, 3, 2)1 
cx!=k! (ptr, 4, 0)1 
cy!=k! (ptr, 4, 1)1 
cz!=k! (ptr, 4,2)1 
WINDOW OUTPUT 11 
CALL drawellipse(ax! , ay ! , bx ! , by ! , mx ! , my ! , ! , pi2 ! ) 1 



CALL setpoint (ax! +mx! , 

CALL drawline (ex! +mx! , 

CALL drawline (mx! -ax! , 

CALL setpoint (bx ! +mx ! , 

CALL drawline (ex! +mx! , 

CALL drawline (mx! -bx ! , 

WINDOW OUTPUT 21 

CALL drawellipse(ax! , az ! , bx ! , bz ! , mx ! , mz ! , ! , pi 2 ! ) 1 

CALL setpoint (ax! +mx! , 

CALL drawline (ex! +mx! , 

CALL drawline (mx! -ax ! , 

CALL set poi nt (bx ! +mx ! , 

CALL drawline (ex! +mx! , 

CALL drawline (mx!-bx! , 

WINDOW OUTPUT 31 

CALL drawellipse (ay ! , az ! , by ! , bz ! , my ! , mz ! , ! , pi2 ! ) c 

CALL setpoint (ay ! +my ! , az ! +mz ! ) 1 

CALL drawline (cy!+my! ,cz!+mz! ) 1 

CALL drawline (my! -ay! ,mz!-az ! ) 1 

CALL setpoint (by! +my! ,bz!+mz! )1 



,ay!+my!)f 

! , cy ! +my ! ) 1 

,my!-ay!) <3 

, by ! +my ! ) 1 

! , cy ! +my ! ) 1 

! , my ! -by ! ) <3 



! ,az!+mz! )1 
! , cz ! +mz ! ) 1 
,mz!-az!) <1 
,bz!+mz! )1 
! , cz ! +mz ! ) 1 
!,mz!-bz!) 1 



91 



3. The Tracer Program 



Amiga 3D Graphic Programming 



CALL drawline (cy!+my! , cz ! +mz ! ) 1 
CALL drawline (ray ! -by ! , mz ! -bz ! ) 
WINDOW OUTPUT 45 
END SUB1 



We are still missing the display routine for the other 10 objects, which 
are fairly easy to develop. You can explore these yourself. Check the 
complete editor listing in the appendices if you run into trouble. 



3.2.3.4 



Data Operations 



Now you're familar with some of the tools that make up an editor, but 
there are still more. Suppose you entered some objects and want to 
work with the first object; or you want to recreate an object and you 
don't remember the data; or you notice that your last input makes no 
sense and you want to delete the object. 

Let's begin with deleting elements in our array. We have several 
options. The first would be to move all objects that lie to the right of 
the one to be erased in array k ! one position to the left. This method 
can take a large amount of time for very large arrays. Another method 
is to give each object a number which states whether it is active or 
deleted. Now we can mark the deleted elements as free. Then when the 
program is running the input routine can search for a free spot in array 
k ! and the new element can be inserted in the free position. How can 
our program find the next free spot quickly? 

There is a simple solution. You create a global variable (kfree) 
which points to a free position. When an object is deleted, the index of 
this object is stored in kfree. What if an element was erased 
previously? Then this information goes into this free position. You 
keep track of this pointer to build a list of free positions of 
k ! (kfree,..,..), for example in k ! (kfree, 0,1). When more objects 
are erased while the program is running, a list of the free element is 
built. This is shown in the diagram below: 



Figure 3.22 



k() : 




kfree 



Elements 1,4,5 and 7 are free 



92 



Abacus 3.2 The Editor 



This task, building a list of the free elements, is taken on by the 
following procedure, which clears the non-zero elements because these 
have a special meaning as initializing elements: 

SUB deleter (ptr) STATICl 
'TASK : delete one bodyl 
' PARAMETER :=>ptr points to the bodyl 
SHARED k! () , kfreel 

IF ptrxO THEN 'not the starting elements 
FOR i=0 TO 5 'Deleted 
FOR j=0 TO 21 

k! (ptr,i, j)=01 
NEXT jl 
NEXT i 1 

k! (ptr,0,0)=-l 'Add body to free listl 
k! (ptr,0,l)=kfree1 
kfree=ptr1 
CALL lefts (ptr) 1 
END IF 1 
END SUB1 

Now to request these as free memory, we add one procedure that marks 
the entire array k ! as free at the start of the program and adds it to the 
free list: 

SUB newelem(ptr) STATICl 

'TASK :get address of free place in listl 
' PARAMETER: <=ptr points to this area*! 
SHARED kfree,k! (),knum1 
IF kfree<knum THEN1 
ptr=kfree1 
kfree=k! (ptr, 0,1)1 
k! (ptr,0,0)=01 
k! (ptr,0,l)=01 
k! (ptr,0,2)=11 
END IF 1 
END SUB1 
1 

These are our own memory management routines, which work on the 
same principle as the Amiga's equivalent operating system procedures. 

To copy an element in the array, we need a pointer to a free memory 
area, and then we write data from one element to another, value for 
value: 

SUB copy (ptr) STATICl 
'TASK :copy one bodyl 
• PARAMETER :=>ptr points to the bodyl 
SHARED k! ()1 

IF ptrxO THEN 'not the starting elements 
old=ptr 'save pointerl 
CALL newelem(ptr) 'create new spacel 
FOR i=0 TO 5 'copyl 
FOR j=0 TO 2f 

k! (ptr,i, j)=k! (old,i, j)1 
NEXT jl 
NEXT if 
END IF1 



93 



3. The Tracer Program Amiga 3D Graphic Programming 



END SUB! 
! 

We need a procedure that can move objects around in the list. We want 
to move objects to the left in the list so the pointer can be lowered to 
element one, and we want to move objects to the right in the list so we 
can increase it past one. We must assume that until now the pointer 
was never negative, contained too large a value, or didn't point to an 
erased element: 

SUB lefts (ptr) STATIC! 

'TASK :get element to left of current elememt! 
' PARAMETER :=>ptr points to current body! 
SHARED k! ()! 
IF ptr><0 THEN ! 

ptr=ptr-l! 
END IF! 
WHILE k! (ptr, 0,0) =-15 

ptr=ptr-l! 
WEN DTI 

CALL showelem(ptr)! 
END SUB ! 

! 
SUB rights (ptr) STATIC! 

'TASK :get element to right of current element! 
' PARAMETER :=>ptr pointer to current body! 
SHARED k! (),knum! 
old=ptr! 
IF ptr<knum THEN! 

ptr=ptr+l! 
END IF! 
WHILE ki (ptr, 0,0) =-1 AND ptr<knum! 

ptr=ptr+l! 
WEND! 
IF k! (ptr, 0,0)=- 1 THEN! 

ptr=old ! 
ELSE! 

CALL showelem(ptr) ! 
END IF! 
END SUB! 



Now we want to describe data manipulation and the enlarging, moving 
and rotation of a shape. 

When the individual coordinates of a vector are multiplied by the same 
constant, the named vector is increased by this factor. When the 
coordinates are multiplied by different factors, the vector is unevenly 
stretched in the three basic directions, an effect that we shall add to our 
program. 

To move our shape we must move its reference point. The new 
reference point can be entered either with the keyboard or the mouse. 

It is more complicated with the rotation. The reference point stays in 
place and the difference vectors are changed. These vectors are rotated 
around three angles in the room according to the following formula: 



94 



Abacus 3.2 The Editor 



( x , y , z ) is the original vector 

(alpha, beta, gamma) are the three angles around which the 

vector should be rotated 

(X, Y, z) is the rotation vector given with the three 

help variables 

a=x*cos (gamma) -y*sin (gamma) 
b=x*sin (gamma) +y*cos (gamma) 
c=a*sin (beta) -z*cos (beta) 

from 

X=a*cos (beta) +z*sin (beta) 
Y=c*sin (alpha) +b*cos (beta) 
Z=b*sin (alpha) -c*cos (alpha) 

This formula must be taken for granted because the proof would fill a 
page. An object should be copied and then rotated, instead of just 
rotating it. It would help the user to be freed of this copy operation. 
Our rotation can can be defined by the following BASIC procedure : 

SUB rotation (ptr) STATICf 
'TASK : rotate body by three angles^ 
• PARAMETER: =>ptr points to the bodyf 
SHARED k! (),grad!,rad!, mini, max! f 
IF ptrXO THENSl 

WINDOW 5, "Rotation", (0, 12 9) - (314, 170) , 4, If 
vx! =grad: *vx!f 
vy ! =grad! *vy ! f 
vz ! =grad ! *vz ! 1 
LOCATE 2, H 
PRINT"V :"1 

PRINT"q<uit, d<o, c<opy&do : "<& 
CALL put3real (vx ! , vy ! , vz ! , 2, 4, 26) 5 

CALL get3real (vx! , vy ! , vz ! , " ", 2, 4, 26, min ! , max ! , 0) \ 
CALL getstring(a$, " ", M qcd", 3, 21, 1) \ 
vx! =rad! *vx! \ 
vy!=rad!*vy!SI 
vz ! =rad! *vz!1l 
WINDOW CLOSE h\ 
WINDOW OUTPUT 4^1 
IF a$>< ,, q" THEN*! 
IF a$="c" THENfl 

CALL copy (ptr) \ 
END IFI 
IF k! (ptr,0,0)>=20 THEN \ 

til=4SI 
ELSE<1I 

til = 3Sl 
END IF1 
FOR i=2 TO till 

a!=k! (ptr,i,0)*COS(vz! )-k! (ptr, i, 1 ) *SIN (vz ! ) \ 
b!=k! (ptr,i,0)*SIN(vz!)+k! (ptr, i , 1 ) *COS (vz ! ) \ 
c!=a!*SIN(vy!) -k! (ptr, i, 2) *COS (vy ! ) \ 
k! (ptr,i,0)=a!*COS(vy!)+k! (ptr, i, 2) *SIN (vy ! ) f 
k! (ptr, i,l)=c!*SIN(vx! ) +b! *COS (vx ! ) SI 



95 



3. The Tracer Program Amiga 3D Graphic Programming 



k! (ptr,i,2)=b!*SIN(vx!)-c!*COS(vx!)< 
NEXT if 

CALL showelem(ptr) $ 
IF k! (ptr, 5, 2) =1 THEN1 

CALL drawelem(ptr)$ 
END IF f 
ELSE 1 

WINDOW CLOSE 55 
END IF! 
END IF! 
END SUB! 



With a few changes this procedure handles enlargement and movements: 

1.) Eliminate the conversion from the different angle systems 

2.) get3real is called in mode -1 for the movement, the check is 
made to see if k ! (ptr,0,0)>=2 and the FOR loops are set 
with: 

k ! (ptr, 1,0) =vx! 
k ! (ptr, 1, 1) =vy! 
k! (ptr, l,2)=vz! 

3.) The instruction for the enlargement is set in the FOR loop: 

k ! (ptr, i, 0) =vx! * (ptr, i, 0) 
k ! ( pt r , i , 1 ) = vy ! * ( pt r , i , 1 ) 
k ! (ptr, i,2) =vz ! *k ! (ptr, i, 2) 

Now two more routines editor are ready for adding to the editor. 



3.2.3.5 Disk Operations 



These operations are basically very simple. The contents of the array 
k ! () are written to the disk, element by element. It should be possible 
to save only certain sections of the data, specified by the top and 
bottom limits of the indices. Before choosing this option in the 
progam, the elements that should be deleted should be marked so they 
are not written to the disk. The editor adds a file extension of .list to 
the filename to distinguish the file from any other file types on disk. 

SUB savelist STATIC! 

'TASK :See save routine for material list 1 

SHARED k! () , knum, legchar$,File$fl 

WINDOW 5, "Save List", (0, 129) - (314, 170) , 0, If 

PRINT "Name:"! 

PRINT "from:l"U 

PRINT "to :"5 

mfrom!=11 

mto!=knumf 



96 



Abacus 3.2 The Editor 



CALL putreal (mto! , 3, 6,10)5 

CALL getstring (FileS, " ", legchar$, 1 , 6, 10) SI 
CALL getint (mfrom! , " " , 2, 6, 10, 1 ! , knum*l ! ) SI 
CALL getint {mto! , " " , 3, 6, 10, mf rom! , knum*l ! ) SI 
IF File$><"" THENSI 

OPEN File$+" .LIST" FOR OUTPUT AS ISI 
quant ity= 01 

FOR i^mfrom! TO mto! "determine number of elements to be 
savedSI 

IF k! (i,0,0) ><-l THENSI 

quant ity=quantity +11 
END IFSI 
NEXT if 

PRINT #1, quantity f 
FOR ptr=mfrom! TO mto! SI 

IF k! (ptr,0,0)X-l THEN 'forget blank elements^ 
FOR i=0 TO SSI 

PRINT #l,k! (ptr,i, 0) ; " , " ; k ! (ptr, i, 1) ;", ";k! (ptr, i,2) f 
NEXT iSI 
END IFSI 
NEXT ptrSI 
CLOSE ISI 

KILL File$+".LIST.info"SI 
END IFSI 

WINDOW CLOSE 5 SI 
WINDOW OUTPUT 4 SI 
END SUB SI 

SI 

SUB loadlist STATICSI 
'TASK :Load list SI 

SHARED k! {) ,knum,ptr, legchar$, File$SI 
WINDOW 5, "Load List ", (0, 129) - (314 , 150) , 0, 1SI 
PRINT "Name: "SI 

CALL getstring (File$, " ", legchar$, 1 , 6, 10) SI 
IF File$><"" THENSI 

OPEN File$f" .list" FOR INPUT AS 1SI 
INPUT #1, quant itySI 
WHILE NOT (EOF (1) ) SI 
CALL newelem(ptr)SI 
FOR i=0 TO 5 SI 

INPUT #l,k! (ptr,i,0) , k ! (ptr, i, 1) , k ! (ptr, i, 2) SI 
NEXT iSI 
WEND SI 
CLOSE ISI 
END IFSI 

WINDOW CLOSE 5 SI 
WINDOW OUTPUT 4SI 
CALL showe 1 em { pt r ) SI 
END SUBSI 
SI 



The procedure does not test for the existence of the file on disk. If the 
user enters a nonexistent name, the following error message appears: 

FILE NOT FOUND 

The program stops and the line with the OPEN instruction is displayed. 
You may wish to add error handling. 



97 



3. The Tracer Program Amiga 3D Graphic Programming 



3.2.3.6 Mouse and Gadgets 



Before we examine the gadgets that will be used in our program, we 
want to show you the mouse check routine we talked about earlier. Our 
mouse check routine executes by pressing the left mouse button and 
reading the coordinates of the mouse position. This should only happen 
when the chosen window is a projection window. It. should not happen 
for our input and output window. In another case MOUSE(3) and 
MOUSE(4) check the X or Y coordinates of the mouse position. These 
coordinates represent the screen coordinates and not the room 
coordinates which interest us. You must also calculate if section, 
enlargement factor, and X correction factor should be considered. To 
mark the position clicked on, the program draws a small cross on the 
screen. Then the mouse coordinates are read: 

' ** READ MOUSE **! 

! 
click :! 

dummy=MOUSE(0)! 

x!=MOUSE (3) / (factor! *xcorrfac! ) 'Get mouse position and 
computeSi 

y ! =MOUSE ( 4 ) / factor ! ! 
n=WINDOW(0) 'window clicked! 
oldwindow=WINDOW(l) 'output window! 
CALL activatewindowS (WINDOW (7) ) ! 
IF n<4 THEN 'was projection windoiw clicked?*! 
WINDOW OUTPUT n! 

LI NE (MOUSE ( 3 ) -1 , MOUSE ( 4 ) ) - (MOUSE ( 3 ) + 1 , MOUSE ( 4 ) ) , 3 ' Draw 
circle! 

LINE (MOUSE (3) , MOUSE (4) -1) - (MOUSE (3) , MOUSE (4 } +1) , 3! 
IF n=l THEN 'compute spatial coordinates! 
mox ! =mx ! +x ! ! 
moy ! =my ! -y ! ! 
ELSE! 

IF n=2 THEN! 
mox ! =mx ! +x ! ! 
moz !=rnz ! -y! ! 
ELSE ! 

IF n=3 THEN! 
moy ! =my ! -x ! ! 
moz ! =mz ! -y ! ! 
END IF! 
END IF! 
END IF! 

mox! =FIX (mox! + . 5) 'round! 
moy!=FIX(moy!+.5)! 
moz!=FIX(moz!+.5)! 
WINDOW OUTPUT 4! 

mo$=STR$ (mox ! ) +", "+STR$ (moy ! ) +", "+STR$ (moz ! ) ! 

LOCATE 10,8 'delete old mouse values and display new 

ones! 

PRINT SPACE$ (2 6)! 
LOCATE 10,8! 



98 



Abacus 3.2 The Editor 



PRINT MID$(mo$,l,26) f 

WINDOW OUTPUT oldwindowf 
ELSE1 

CALL checkgadget 'was a gadget clicked? 
END IFf 
RETURN f 



This subroutine is incorporated into our program with ON MOUSE 
GOSUB click. 

If you have carefully examined the subroutine, the call from 
checkgadget should attract your attention. This is where we 
implement the gadgets. We have chosen the following route: 

The init gadget routine lets you establish where on the screen a 
certain gadget of a specific height and width should appear. All of this 
information goes into a special global array. When the user presses the 
left mouse button, the checkgadget routine is called. It checks for 
whether the mouse pointer lies inside of the gadget. If so, the following 
two possibilities exist: 

1.) When the gadget is a slider, the old slider must be deleted and 
drawn at the new position. The position of the orginal slider is 
saved in the gadget % array in the fourth position. 

2.) When the gadget is an icon, this icon whose picture information 
is in the array gadget s% is either inverted or is given a 
completely new icon graphic. This screen information is loaded 
at the start of the program with GET and is accessed by PUT. 
The additional gadget is stored temporarily in gadget % (4). 

Another routine ensures that the gadgets which are no longer necessary 
are deleted from the screen: 

SUB checkgadget STATICSI 

'TASK :test whether a gadget has been clicked f 
SHARED gadget%() , gadget s%() f 
dunimy=MOUSE(0)fl 
ax=MOUSE(3) 'Mouse positional 
ay=MOUSE(4)f 
i=0fl 
WHILE i<=10 'search entire arrays 

x%=gadget% (i, 0) 'get values from array f 
y%=gadget%(i,l)f 
h%=gadget%(i,2)f 
l%=gadget%(i,3)fl 
valu%=gadget%(i,4)fl 
wind%=gadget% (i,5) <fl 
yes%=gadget% (i, 6) f 

none%=gadget% (i, 7) 'Mouse over gadget ?f 

IF x%<ax AND x%+l%>ax AND y%<ay AND y%+h%>ay AND x%>=0 AND 
WINDOW (0)=wind% THENf 

old=WINDOW(l) 'reserve output window^ 

WINDOW OUTPUT wind% 'delete old slider draw new onef 

IF yes%=-l THENf 

LINE (valu%+x%+l,y%+l) - (valu%+x%+l, y%+h%-l) , Of 



99 



3. The Tracer Program Amiga 3D Graphic Programming 



valu%=ax-x%-l < 5 

LINE (valu%+x%+l,y%+l)-(valu%+x%+l,y%+h%-l) ,31 
gadget% (i, 4)=valu% 'get new valuel 
ELSEl 

IF none%=-l THENl 

IF valu%=l THEN 'first time, invert itfl 
gadget% (i, 4) =01 

LINE (x%,y%)-(x%+l%,y%+h%),0,bf1 
PUT (x%,y%),gadgets%(yes%) ,PRESET1 
ELSE f 

gadget% (i, 4)=1 'else return 1 
LINE (x%,y%)-(x% + l%,y%+h%) ,0,bf1 
PUT (x%,y%) ,gadgets%.(yes%) 1 
END IFl 
ELSE 1 

IF valu%=l THEN 'first time, display no output 5 
gadget% (i, 4) =01 

LINE (x%,y%)-(x%+l%,y%+h%),0,bffl 
PUT (x%,y%) , gadgets% (none%)1 
ELSE 1 

gadget% (i, 4) =1 "else yes output^ 
LINE (x%,y%)-(x% + l%,y%+h%),0,bf<5 
PUT (x%,y%),gadgets%(yes%)1 
END IFSI 
END IFfl 
END IFl 

WINDOW OUTPUT old 'old output window active*?! 
i=10 1 
END IF1 
i=i + H 
WEND1 
END SUB 1 

1 
f 

SUB initgadget (x%, y%, h%, 1%, valu%, wind%, nr%, yes%, none%) STATIC! 
'TASK zplace a new gadget in the gadget array gadget%{)SI 
• PARAMETER :->x%,y% Position of upper left cornerl 
' h%,l% border height and lenghtl 

' valu% Start valued 

' wind% Output windowl 

' yes%,none% if yes%=-l,then sliderl 

' if none%=-l , gadgets inverts when clicked^ 

' else display another gadgetl 

' yes% and none% supply the indices for 

graphic information^ 

' of the array gadgets 1 

' <=nr% Position of the gadgets in array SI 

SHARED gadget%() ,gadgets%()1 

IF x%>=0 AND y%>=0 AND h%>=2 AND 1%>=3 AND valu%>=0 AND 
valu%<l% AND wind%>0 THENl 
MOUSE OFF1 
old=WINDOW(l)fl 
WINDOW OUTPUT wind%1 
IF yes%=-l THEN1 

LINE (x%,y%)-(x%,y%+h%)1 
LINE -(x%+l%,y%+h%)1 
LINE -(x% + l%,y%)1 
LINE -(x%,y%)1 

LINE (valu%+x%+l,y%+l)- (valu%+x%+l,y%+h%-l) , 31 
ELSE1 

IF valu%=l THEN1 

PUT (x%,y%) ,gadgets%(yes%) 1 



100 



Abacus 3.2 The Editor 



ELSE5 

PUT (x%,y%) ,gadgets%(none%) <5 

END IFfl 
END IFSl 
nr%=0^[ 
WHILE gadget% (nr%, 0) ><-! AND nr%<=9 5 

nr%=nr% + 111 
WEND5 
IF gadget%(nr%,0)=-l THEN f 

gadget%(nr%,0)=x%5 

gadget%(nr%,l)=y%5 

gadget%(nr%,2)=h%fl 

gadget%(nr%,3)=l%5 

gadget% (nr%, 4)=valu%5 

gadget% (nr%, 5) =wind%5 

gadget% (nr%, 6) =yes%l 

gadget% (nr%, 7) =none%<H 
END IF f 
MOUSE om 

WINDOW OUTPUT oldSl 
END IFfl 
END SUB5 

SUB deletegadget (i) STATIC^ 
'TASK : delete a gadget^ 
' PARAMETER: =>i Index of gadgets in array 

SHARED gadget%()5 

IF i>=0 AND i<=10 THENSl 
gadget% (i,0)=-lSI 

END IF5 
END SUB SI 



As an example for using this procedure we want to present two routines 
from the editor. Five real values must be read into this editor (a red 
value, green value and blue value, a value that tests for the brightness 
in the shadows and a reflection factor). All of these values must be 
between zero and one. Because a color should be established using the 
red, green, and blues values, it is very helpful if the user can see this 
color on the screen, which is built using the PALETTE 2,..,..,.. 
instruction. The routine to indicate a material element is here also (the 
opposite of s ho we 1 em): 

SUB showmat (matptr) STATIC^ 

'TASK :See corresponding routine for the body list f 
SHARED mat! () , nrl%, nr2%, nr3%, nr4%, nr5%, nr6%5 
CLS5 

PRINT "Material: "5 
CALL putreal (matptr*l! ,1,10, 10)<1I 
IF matptr ><0 THENSl 

LOCATE 1,205 

PRINT "R+G+B="5 

PALETTE 2, mat! (matptr, 0) , mat! (matptr, 1) , mat ! (matptr, 2) SI 

LINE (250,0)-(260,7) ,2,bf1 

PRINT "Red : "5 

PRINT 1 

PRINT "Green :"f 

PRINT 1 

PRINT "Blue : "fl 



101 



3. The Tracer Program Amiga 3D Graphic Programming 



PRINT 1 

PRINT "Shadow : "SI 
PRINT SI 

PRINT "Mirroring :"SI 
wl%=mat! (matptr, 0)*101SI 
w2%=mat ! (matptr, 1) *101SI 
w3%=mat! (matptr, 2) *101SI 
w4%=mat! (matptr, 3) *101ST 
w5%=mat! (matptr, 4) *101 f 

CALL initgadget (110, 8, 10, 102, wl%, 5, nrl%, -1, -1) SI 
CALL initgadget (110, 24, 10, 102, w2%, 5, nr2%, -1, -1 ) SI 
CALL initgadget (110, 40, 10, 102, w3%, 5, nr3%, -1,-1) SI 
CALL initgadget (110, 5 6, 10, 102, w4%, 5, nr4%, -1, -1) 5 
CALL initgadget (110, 72, 10, 102, w5%, 5, nr5%, -1,-1) 
CALL initgadget (110,88,15, 30, 1, 5, nr6%, 0, -1 ) SI 
END IFSI 
END SUBSI 



The zero in the last initgadget call is the address of the OK gadget 
which must be clicked to end data input. 

The routine to read the material data is just as easy as the above 
procedure. It is called after showmat: 

SUB getmat (matptr) STATICS! 

'TASK : see corresponding routine for the body list SI 

SHARED mat! () , gadget% ( ) , nrl%, nr2%, nr3%, nr4%, nr5%, nr6%SI 

CALL showmat (matptr) SI 

WHILE gadget% (nr6%,4)XOSI 

PALETTE 2,gadget% (nrl%,4) /100,gadget% (nr2%, 4) /100, 
gadget% (nr3%,4) /100SI 

WEND SI 

mat ! (matptr, 0) =gadget% (nrl%, 4) / 1 1 SI 

mat ! (matptr, 1) =gadget% (nr2%, 4) /1Q1SI 

mat ! (matptr, 2) -gadget % (ni3%, 4) / 101 SI 

mat ! (matptr, 3) -gadget% (nr4%, 4) /101SI 

mat ! (matptr, 4) =gadget% (nr5%, 4) /101SI 

CALL deletegadget (nrl%)SI 

CALL deletegadget (nr2%) SI 

CALL deletegadget (nr3%) SI 

CALL deletegadget (nr 4%) SI 

CALL deletegadget (nr5%) SI 

CALL deletegadget (nr 6%) SI 
END SUB SI 



This was the last important routine for creating our ray tracer editor. 



3.2.4 Tips on Writing an Editor 



What we have presented so far is a collection of procedures. To get a 
complete program, additional functions must be inserted. One problem, 
for example, is how these functions should be accessed by the user. 



102 



Abacus 3.2 The Editor 



Should there be individual commands that only run in the material 
editor, reconstruct the screen, or move the section? So that the user is 
spared a lot of unnecessary typing, it may be better to have all 
functions in a menu and combine this so some important functions can 
be activated by pressing a key. The important procedures for this are 
very easy and are basically a row of IF statements. 

Next all of the global variables must be initialized and the global arrays 
dimensioned. A screen and four windows for the display and the text 
input and output be opened. The arrays k ! and mat ! should be linked 
at the beginning, declare all the elements as free, and put them in the 
free list. 

It is useful to be able to change from the actual object element to any 
other. The show function displays the object in the projection 
windows (that means with another color). This is so you don't lose the 
overview of the picture with large data sections. 

It is also important to be able to leave the program without having to 
execute a reset. A Quit procedure which checks if the user would 
actually like to quit the program is needed, perhaps using a requester. 

Use the routines and ideas presented to create your own editor or see the 
complete listing in the appendices. The real fun of programming is in 
creating your own programs. 



103 



3. The Tracer Program Amiga 3D Graphic Programming 



3 . 3 The Main Program 



You probably noticed that we're aiming toward a specific goal. All of 
the routines listed up until now can be combined to make a complete 
program. The object editor is a self-sufficient module called from the 
main program. The tracer program has also been built using modules 
that can be combined to make a complete program or can be 
incorporated into your own programs. 

The complete listing of the tracer program is in Appendix B. The 
example programs that follow contain some BASIC lines that must be 
entered on one line in AmigaBASIC, even though they appear on two 
lines in this book. Formatting the program listings to fit into this 
book has caused some long BASIC lines to be split into two lines. To 
show where a BASIC line is actually ended a H will appear. This 
character only shows when the <Return> key should be pressed in the 
BASIC editor. For example, the following line is split into two lines 
in this book, but must be entered as one line in AmigaBASIC: 

WinDef NWindow, 100, 50, 460, 150, 32+64+512&, 15&+4096&, 
0&, Title$f 

The f shows the actual end of the BASIC line. 



3.3.1 The Remaining Tracer Routines 



Now we come to the routines that are important to the completion to 
our main ray tracing program. 

First we want to describe the Raster I nit routine. The user and 
display screens are constructed in this routine. All input takes place on 
the user screen. The wire model and shadowed picture appear on the 
display screen. The tracer program functions in all screen modes, and 
works in either user mode (with 60/80 characters per line): 

Rasterlnit:^ 

* Select resolution and display mode SI 

WINDOW CLOSE 2 » delete any windows andSI 

SCREEN CLOSE 1 » screens f 
f 

WINDOW 1,"", (0,0)- (631, 185) , 6 ' new window with Status-linefl 
SI 

"PALETTE 0,0,0,0 ' Colour for user screen*!! 

•PALETTE 1,1,1,1 f 

•PALETTE 2, .4, .4,11 



104 



Abacus 3.3 The Main Program 



NWBase& = WINDOW (7 )! 

NRastPortS = WINDOW (8)! 

NWScreenfi = PEEKL (NWBase&+4 6) ! 

' Base address of Window-Structured 

' from which the screen structure is taken*! 

• RastPort belongs with the WINDOW () function! 
! 

Status$ = " Status: Select resolution"+CHR$ (0) ' Status 
line output! 

dummy = SetWindowTitles (NWBase&, SADD (Status$) , 0) ! 
! 

DisplayM$(0) - " Normal "! 

DisplayM$(l) = " Hold and Modify"! 

DisplayM$(2) = " Extra Halfbrite"! 

! 

XResl$(0) = " Normal"! 

XResl$(l) = " HIRES "! 

! 

YResl$(0) = " Normal " ! 

YResl$(l) = " Interlaced"! 

! 

x(0) - 0:x(l) = 0:x(2) = 0:x(3) = 4! 

' Which values or strings at which position ?! 
! 

y = 0! 

' topmost line = Start line! 
! 

Modulo (0) = 3! 

Modulo (1) = 2! 

Modulo (2) = 2! 

Modulo (3) - 6! 

1 How many values for each selection line ?! 
! 

COLOR 1! 
! 

Colours (0) - 1! 

Colours (1) - 2! 

Colours (2) = 2! 

Colours (3) = 2! 

1 First line => white rest of the lines => blue! 

! 
Outg:! 

LOCATE 10,21! 

COLOR Colours (0)! 

PRINT "Display mode : "; DisplayM$ (x (0) ) ! 

LOCATE 12,21! 

COLOR Colours (1)! 

PRINT "X-Resolution : ";XResl $ (x (1 ) ) ! 

LOCATE 14,21! 

COLOR Colours (2)! 

PRINT "Y-Resolution : "; YResl$ (x (2) ) ! 

LOCATE 16,24! 

COLOR Colours (3)! 

PRINT "BitPlanes : ";x(3)+l! 
! 

Waiter: a$ = INKEY$! 

IF a$ = "" THEN Waiter! 

! 

IF a$ = CHR$(30) THEN x(y) = (x(y)+l) MOD Modulo (y) ! 

IF a$ = CHR$(31) THEN x(y) = x(y)-l ! 

' CRSR Left /Right! 



105 



3. The Tracer Program Amiga 3D Graphic Programming 



IF x(y) < THEN x (y) = Modulo (y) -If 
IF a$ = CHR$ (28) THEN f 

Colours (y) = 2f 

y = y-lfl 
END IFf 
' CRSR Upfl 
1 

IF a$ = CHR$(29) THENf 

Colours (y) =21 

y = (y+1) MOD 4f 
END IF5 
' CRSR Downf 

IF y<0 THEN y=3fl 

Colours (y) = If 
1 

IF (x(0) > 0) AND (y=0) THENf 

x(l) = ■ Select HAM or Halfbrite f 

x(3) = 5 ' 5+1 BitPlanesf 

Modulo (3) = Sf 
END IFf 

IF x(0)>0 THEN x(3) =5 ' Number of BitPlanes unchanged by 
• HAM or Halfbrite model 

IF (x(0) = 0) AND (x(l)Ol) THEN 1 
Modulo (3) - 51 

IF x(3) > 4 THEN x(3) = 4 ' Maximum 4+1 BitPlanes! 
END IF ' in Normal Model 

I 
IF (x(l) = 1) AND (y - 1) THEN! 

x(0) = ' HIRES and Normal! 

IF x(3)>3 THEN x(3) = 3 ' Maximum 3+1 BitPlanes ! 
Modulo (3) = 4! 
END IF! 
! 

IF a$<> CHR$(13) THEN GOTO Outg! 
! 

COLOR If 
! 

RasterW%= (x (1 ) +1 ) *320! 

RasterH%=(x(2)+l)*200 'PAL- resolution = 256! 
! 

IF x(0) =1 THEN Modus% - &H800 ' HAM! 

IF x(0) =2 THEN Modus% = &H80 'HalfBrite! 

IF x(l) =1 THEN Modus% = &H8000 'HIRES! 

' (HAM, Halfbrite) and HIRES close the same way ! 
! 

IF x(2) =1 THEN Modus% = Modus% OR 4 'LACE! 
! 
CLS! 

RasterT% = x(3)+l! 
! 

IF RasterT% = 6 THEN RasterT% = 5! 
1 If HAM, open a normal screen ! 
' (max. 5 BitPlanes) ! 
! 

IF FRE(-l) < (RasterW%/8*RasterH%*RasterT%)+5000 THEN! 
CLS! 



106 



Abacus 3.3 The Main Program 



CALL Printlt ("Insuf ficent memory for bitmap 
! ! !",100, False)! 

CALL Printlt ("Please try a lower resoluiton or number of 
bitmaps !!! ", 130, False) ! 

! 

CALL DialogBox ("Ok", 1 , True, xlb%, ylb%, x2b%, y2b%, False) ! 

CALL DoDialog(n%,l,-l, -1 , -1, -1, xlb%, ylb%, x2b%, y2b%, -1 , -1, - 

1,-D ! 
CLS! 

GOTO Outg! 
END IF! 

! 
SCREEN l,RasterW%,RasterH%,RasterT%,x (1) + (x (2) *2) +1! 

■ Width , Height , Depth , Model 
! 
WINDOW 2,"", (0,0)-(RasterW%-9,RasterH%-15) ,0,1! 

1 Window layer! 
! 
RasterT% = x(3)+l! 

1 old RasterT value! 
! 

WBase& = WINDOW (7)! 
WScreen& = PEEKL (WBase& + 46) ! 

1 Extract address of the new screen from window addrress! 
! 
POKEL WBase&+24,&Hl00 OR &H800 OR 65536&! 

1 Window Flags change: Borderless, RBMTrap, NoCareRef resh! 
! 

Viewports = PEEKL (WBase&+46) +44! 
ColorMap& = PEEKL (Viewport & + 4 ) ! 
RastPort& = Viewport&-f 40! 
BitMap& = WScreen&+184! 
! 

Adr = PEEKL(RastPort&+4)+8 • BitPlanes for loading! 
FOR i=0 TO RasterT%-l ' and saving! 

BitPlanesS (i) = PEEKL (Adr+4*i) ! 
NEXT i! 
! 

BitPlane6& = BitMap&+28! 

1 Where do you want the sixth bitplane address placed ?! 
! 
Depths = BitMap&+5! 

1 Where do you want the new depth placed ?! 
! 

CALL SetRast& (RastPortS, 0) ! 
CALL SetRGB4& (Viewports, 1, 15,15, 15) ! 
CALL SetRGB4& (Viewports, 0, 0, 0, 0) ! 

1 Clear new screen and set background ! 
! 
IF RasterT% = 6 THEN! 

GroesseS = RasterW%* (RasterH%\8) ! 

FlagsS = 65536S+2 ' MEMF_CHIP | MEMF_CLEAR! 

MemS = AllocMemS (GroesseS, FlagsS) ! 
IF Mem& = THEN! 
CALL Scroff! 

CALL Printlt ("Not enough memory for sixth BitPlane 
! ! ! ",100, False)! 

CALL DialogBox ("Sorry 
!", 1, True, xla%,yla%, x2a%,y2a%, False)! 
! 

CALL DoDialog (n%, 1,-1, -1,-1,-1, xla%, yla%, x2a%, y2a%, -1,-1,- 
1,-D! 



107 



3. The Tracer Program Amiga 3D Graphic Programming 



GOSUB CloseltSI 
RUNSI 
END IFSI 
SI 
POKE Depths, 6 SI 

' New depthSI 
SI 

POKEL BitPlane6&,Mem&SI 
BitPlanes& (5) =Mem&SI 

1 Poke address of the sixth BitPlaneSI 
SI 
POKEW Viewport&+32,Modus%SI 

' Poke for display mode POKENSI 
SI 
dummy = RemakeDi splay (dummy &) SI 

1 compute new display SI 
END IF SI 

Status$ = " Status: Initializing"+CHR$ (0) SI 
CALL SetWindowTitlesS (NWBaseS , SADD (Status$) , 0)< 

CALL ScroffSI 

CALL SetDrMd& (RastPortk, i) SI 



RasterWl% 


= RasterW%-l 


' 319/639SI 


RasterHl% 


= RasterH%-l 


' 199/399SI 


RasterW2% 


= RasterW%/2 


' Screen middle' 


RasterH2% 
SI 
FactorX = 


= RasterH%/2SI 




(x(l)+l)/2SI 




FactorY = 


(x(2)+l)/2SI 





POKEW OSModus&,Modus%SI 
POKEL OSRastPort&,RastPort&SI 
POKEW OSRasterWl&,RasterWl%SI 
POKEW OSRasterHl&,RasterHl%SI 

MaxColour% = 2 A RasterT%SI 
IF (RasterT% = 6) THENSI 

IF (Modus% AND &H800) = &H800 THEN SI 

MaxColour% = 16 ' HAMS1 

ELSESI 

MaxColour% = 64 'HalfbriteSI 

END IF1 
END IFSI 

POKEW OSMaxColour&,2 A RasterT% 'If HAM: 64 Colour ! c 
DIM Colour (MaxColour%, 3) SI 
I 
FOR m%=0 TO 3 SI 

Colour (l,m%)=0 'BlackSI 

Colour (2, m%)=l 'WhiteSI 
NEXT m%SI 

IF (Modus% AND &H80) = &H80 THEN 'HalfBriteSI 
MF%=MaxColour%/2SI 
II 

Colour (MF%+1,0)=MF%SI 
Colour(MF%+2,0)=MF%+lSI 
FOR m%=l TO 3SI 

Colour (MF%+l,m%)=0SI 
Colour (MF%+2,m%)=.5SI 



108 



Abacus 3.3 The Main Program 



NEXT m%! 

RESTORE OptimaleHBColour! 
ELSE! 

MF%=MaxColour%! 
RESTORE OptimaleColour! 
END IF! 
! 

FOR n% = 3 TO MF%! 
READ r%,g%,b%! 
! 

Colour (n%.0)=n%-l! 
Colour (n%,l)=r%/15$ 
Colour (n%,2)=g%/15! 
Colour (n%, 3) =b%/15f 

CALL SetRGB4& (Viewports, n%-l, r%,g%,b%) ! 
SI 

IF (Modus% AND &H80)<>0 THEN 'HalfBrite! 

Colour (n%+MF%, 0) =n%+MF%! 
FOR m%=l TO 31 

Colour (n%+MF%, m% ) = (INT (Colour (n%,m%) *1 5) \2)/15! 
NEXT m%! 
END IF! 
! 

NEXT n%! 

' => Colour (n, 0) = color index, SI 
1 Colour (n,l. .3) = RGB brightness! 
SI 

1 Poke colors into assembler routines array:! 
! 

FOR n%=0 TO MaxColour%-l! 

POKEW OSColour&+n%*8,Colour(n%+l,0)! 
FOR m%=l TO 3! 

POKEW OSColour&+n%*8+m%*2, Colour (n%+l, m%) *1024! 
NEXT m%! 
NEXT n%! 
CLS! 
RETURN! 

The Rasterlnit routine also sets the colors for the user screen. If 
you are not happy with the default colors these may also be changed: 

ColorPalette:! 

Status$ = " Status: Color change"+CHR$ (0) ! 

CALL SetWindowTitles&(NWBase&,SADD(Status$) ,0)! 
! 

GOSUB DeleteMenu! 
! 

CALL SetRast& (RastPort& , 0) ! 

CALL Scron! 

CALL Printlt ("Which color to change ?", 100, True) ! 

! 

NumCol = MaxColour%! 

IF NumCol = 64 THEN NumCol = 32 ' Halfbrite ?! 

Widthe = (RasterW%-40) /NumCol! 

LINE ( (20+1) ,l)-(20+Widthe-l,RasterH%/10-l) ,l,b ! 

FOR i=l TO NumCol-1! 

LINE ( (20+i*Widthe+l) , 1) - ( (20+ (i + 1) *Widthe) -l,RasterH%/10- 
1 ) , i , BF! 

IF MaxColour% = 64 THEN 'Halfbrite Colour output! 

LINE ( (20 + i*Widthe+l) , RasterH%/10) - ( (20+ (i + 1 ) *Widthe) - 
l,RasterH%/5-l) ,i+32,BF! 



109 



1 



3. The Tracer Program Amiga 3D Graphic Programming 



END IFf 
NEXTl 
1 
LoopArl 
CALL Empty Buffer si 

WHILE MOUSE (0) = 01 

WENDl 

1 

x = MOUSE (1)1 

y = MOUSE (2)1 

1 

IF (x < 20) OR (x > RasterW%-20) THEN 1 

GOTO LoopArl 
END IF 1 
IF (y < 1) OR (y > RasterH%/10) THENl 

GOTO LoopArl 
END IF1 

Colr% = INT ( (x-20) /Widthe) ' which colors was clickedl 

CALL Scroffl 

red=INT (Colour (Colr%+l , 1 ) *15 . 5) 1 

green=INT (Colour (Colr%+l, 2) *15.5)1 

blue=INT (Colour (Colr%+l, 3) *15. 5) 1 

1 

LOCATE 10,11 

PRINT " red-component (0..15) : ";1 

CALL Formlnputlnt (red, 30 ! , ! , 15 ! ) 1 



LOCATE 11,11 

PRINT " green-component (0..15) : ";1 

CALL Formlnputlnt (green, 30 ! , ! , 15 ! ) 1 

1 

LOCATE 12,11 

PRINT " blue-component (0..15) : ";1 

CALL Formlnputlnt (blue, 30 ! , ! , 15 ! ) 1 

1 

Colour (Colr%+l, 1) =red/151 

Colour (Colr%+l, 2) =green/151 

Colour (Colr%+l, 3) =blue/151 
1 

POKEW OSColour&+Colr%*8+2, red/15*10241 

POKEW OSColour&+Colr%*8+4,green/15*10241 

POKEW OSColour&+Colr%*8+6,blue/15*10241 
1 

IF MaxColour%=64 THEN "ExtraHalfBritel 

Colour(Colr%+33,l)=(red\2) /151 
Colour (Colr%+33, 2) =(green\2)/151 
Colour (Colr%+33, 3) = (blue\2) /151 
1 

POKEW OSColour&+Colr%*8+258, (red\2) /15*10241 
POKEW OSColour&+Colr%*8+260, (green\2) /15*10241 
POKEW OSColour&+Colr%*8+262, (blue\2) /15*10241 
1 

END IF1 

1 

CALL 
SetRGB4& (Viewports, Colr%, CINT (red) , CINT (green) , CINT (blue) ) ( 
1 

CALL DialogBox ("End", 0, True, xla%,yla%, x2a%,y2a%, False) 1 

CALL DialogBox ("Next 
color", 2, False, xlb%,ylb%, x2b%,y2b%, False) 1 



110 



Abacus 33 The Main Program 



CALL DoDialog (n%, 0, xia%, yla%,x2a%, y2a%, -1, -1, -1, - 
1, xlb%, ylb%, x2b%, y2b%) ! 

CLS! 
5 

IF n% = 2 THEN ! 
CALL Scron! 
GOTO LoopA! 

END IF! 

Newone! = True! 

Hg = False! 

GOSUB MakeMenu! 
RETURN'S 
'! 

The colors of the user screen can, if you want, be changed in the 
Rasterlnit routine by using the PALETTE statement. 

We have provided for file access between computer and disk. You can 
build object definitions with the editor and then load existing 
definitions from disk into the tracer program. Or you can merge 
different object definitions and save all of the objects together on disk: 

« ****************•************•**<][ 

• * 'SERVICE' - Module *! 

'! 

Saver: ! 

' Save array K() to disk! 
GOSUB Directory*! 
5 

Status$ = " Status: Object Saver"+CHR$ (0) ! 
CALL SetWindowTitles& (NWBase&, SADD (Status $) ,0)5 
! 

LOCATE 3,15 

PRINT " Under what name do you want the object saved?"! 
PRINT ! 

PRINT " Filename : ";! 
dn$ = ""! 

CALL FormlnputSt ring (dn$,30!)! 
5 

CLS! 

IF dn$<> ,,K THEN! 

dn$ = dn$ + ".LIST"! 
OPEN "O",#l,dn$,1024! 
PRINT #l,NumberK! 
FOR n%=l TO NumberK! 
FOR p%=0 TO 55 

PRINT #l,K(n%,p%,0),K(n%,p%,l) ,K(n%,p%,2)! 
NEXT p%! 
NEXT n%! 
CLOSE #15 
'The following will delete icons when included:! 
' dn$ = dn$+".info"! 
KILL dn$! 
END IF! 
CLS! 

GOSUB MakeMenu! 
RETURN! 
*5 



111 



3. The Tracer Program Amiga 3D Graphic Programming 



Loader: SI 

1 Load array K() from diskl 
GOSUB Directory^ 
1 

Status$ = " Status: Object Loader"+CHR$ (0) 1 
CALL SetWindowTitles&(NWBase&,SADD(Status$) ,0)1 
1 

LOCATE 3,11 

PRINT " Which object do you wish to load? "31 
PRINT 1 

PRINT " Filename : ";1 
dn$ = ""1 

CALL FormlnputSt ring (dn$,30!)1 
1 

CLS1 

IF dn$ <> "" THEN1 

dn$ = dn$+".LIST"1 

OPEN "I",#l,dn$, 10241 

INPUT #l,NumberKl 

LOCATE 10,101 

PRINT "Total ";NumberK;" Object ("+dn$+") . "1 

PRINT1 

PRINT " Maximum number of objects? ";1 

MaxNumber = NumberKl 

CALL Formlnputlnt (MaxNumber, 30 ! , 1 ! , NumberK) 1 



IF NumberK > MaxNumber THEN NumberK = MaxNumber 1 



ERASE K1 

DIM K (MaxNumber, 5, 2)1 
1 

FOR n%=l TO NumberKl 
FOR p%=0 TO 51 

INPUT #l,K(n%,p%,0) ,K(n%,p%,l) ,K(n%,p%,2)1 
NEXT p%1 
NEXT n%1 
CLOSE #11 
Newone! = Truel 
Start% = 11 
END IF1 
CLS1 

GOSUB MakeMenul 
RETURN1 
'1 
Merger: 1 

' Elements appended to available array K()1 
IF (MaxNumber-NumberK) <= THEN1 

Status$ = " Status: Object Merger"+CHR$ (0) 1 
CALL SetWindowTitlesS (NWBase&, SADD (Status$) , 0) 1 
1 

a$ = "Insuf ficent memory for more objects! !! "1 
CALL Printlt (a$, 100, False) 1 

a$ = "Please select New to create a cleared array K()!"1 
CALL Printlt (a$, 130, False) 1 

CALL DialogBox ("OK", 1, True, xla%, yla%, x2a%,y2a%, False) 1 
1 

CALL DoDialog(n%,l,-l,-l,-l,-l,xla%,yla%,x2a%,y2a%,-l,-l, 
1,-1)1 
ELSE 1 

GOSUB Directoryl 
1 

Status$ = " Status: Object Merger"+CHR$ (0) 1 



112 



Abacus 3.3 The Main Program 



CALL SetWindowTitlesS (NWBase&, SADD (Statu s$) , 0)SI 
SI 

LOCATE 3,1 SI 

PRINT " Which object would you like to merge? "SI 
PRINTS! 
dn$ = "" SI 

PRINT " Filename : «'; SI 
CALL FormlnputString (dn$,30!)Si 
SI 

CLSSi 

IF dn$ <> "" THENSI 
dn$ = dn$ + ".LIST"SI 
OPEN "I",#l,dn$,1024SI 
INPUT #l,xf 
SI 

LOCATE 6,1 SI 

PRINT " Total ";x;" Objects ( " + dn$ + " ) . "SI 
PRINT 'SI 

PRINT " Sufficent memory for "; MaxNumber-NumberK; " 
Objects. "SI 

PRINTSI 

PRINT " How many merges? ";SI 
num = xSI 

CALL Formlnputlnt (num, 30 ! , 1 ! , 10 00 ! ) SI 
SI 

IF x<num THEN num = xf 

IF MaxNumber-NumberK<num THEN num = MaxNumber-NumberKSI 
SI 

IF num>=l THENSI 

FOR n%=NumberK+l TO NumberK+numSI 
FOR p%=0 TO 5SI 

INPUT #l,K(n%,p%,0) , K(n%,p%,l) , K (n%, p%, 2) SI 
NEXT p%SI 
NEXT n%SI 

NumberK = NumberK+numSI 
Newone! = True SI 
Start% = If 
END IFSI 
CLOSE #lf 
END IFSI 
END IFSI 
CLSSI 

GOSUB MakeMenuSI 
RETURN! 



When merging objects, array K ( ) , where the objects are stored 
internally, must be large enough to accommodate these objects. The 
number of array elements is set in Array I nit. Any object 
definitions stored previously here are lost: 

Arraylnit : SI 

1 Create new array K() SI 

Status$ - " Status: New array creation"+CHR$ (0) SI 
CALL SetWindowTitlesS (NWBase& , SADD (Status$) ,0)SI 
SI 
GOSUB DeleteMenuSI 
SI 

LOCATE 10,1! 

PRINT " Maximum number of objects -■= " ; SI 

a = Ma xN umber SI 



1 13 



3. The Tracer Program Amiga 3D Graphic Programming 



CALL Formlnputlnt (a, 30 ! , ! , 1000 S ) ! 
! 
IF MaxNumber <> a THEN! 

MaxNumber = a SI 

NumberK=Q! 

ERASE K! 

DIM K (MaxNumber, 5, 2)! 

Start % = 0! 
END IF! 
qi 

CLS! 

GOSUB MakeMenu! 
RETURNS 

'SI 
'SI 

In addition to object definitions, you can also load new material 
constants created in the editor from disk into the tracer: 

LoadMat:! 

GOSUB Directory*!! 
SI 
Status$ = " Status: Material constants loader" +CHR5 (0) SI 
CALL SetWindowTitlesS (NWBaseS , SADD (Status$) , ) SI 
SI 

LOCATE 3,1 SI 

PRINT " Which material would you like to load?"! 
PRINT SI 

PRINT " Filename : ";SI 
SI 

dn$ = ""SI 

CALL FormlnputString (dn$, 30 ! ) SI 
Tl 

IF dn$<>"" THEN SI 
dn$=dn$+".MAT"! 
OPEN " 1 " , # I , dn$ SI 
matptr = 1ST 
INPUT #1, Number Mat SI 
ERASE Mat SI 

DIM Mat (NumberMat,6)SI 
WHILE NOT (EOF (1) ) SI 
FOR i = TO 6SI 

INPUT #l,Mat (matptr, i) SI 
NEXT iSI 

matptr = matptr+1! 
WEND! 
CLOSE #1SI 
END IFSI 
CLSSI 

GOSUB MakeMenu! 
RETURNS! 

We have added a routine for you that makes it possible to save the 
screens created by the tracer program as an IFF (Interchange File 
Format) file. A picture saved in this format can be used with any 
program that supports IFF (e.g., DeluxePaint®): 

S creenSave r : SI 

GOSUB Directory! 



114 



Abacus 3.3 The Main Program 



Status$ = " Status: Screen saver"+CHR$ ( 0) 5 
CALL SetWindowTitlesS (NWBaseS , SADD (Status$) , ) SI 
1 

LOCATE 3,111 

PRINT " Under what name would you like the screen saved? "SI 

PRINT 1 

PRINT " Filename : ";1 

IFFFile$ = ""SI 

CALL FormlnputString (IFFFile$, 30 ! ) 1 

1 
IF IFFFile$ <> "" THENl 
SI 
Handles = ' File HandleSI 
Buffers - • Buffer memoryl 
' reserve bufferSI 

FlagsS = 65537& ' MEMF_PUBLIC | MEMF_CLEARSI 
BufferSizeS = 360SI 

Buffers = AllocMemS (BufferSizeS , FlagsS) SI 
IF Buffers = THENSI 

Dialog$ = "No more memory! ! ! "SI 
GOTO EndSaveSI 
END IFSI 
SI 

ColorBufferS = BufferSSI 
SI 

Nulls = 01 
PadByte% - OSI 
SI 

IF RasterW% = 320 THENSI 
IF RasterH% = 200 THENSI 

Aspect% = SHA0BSI 
ELSESI 

Aspect% = SH140BSI 
END. IFSI 
ELSESI 

IF RasterH% = 200 THENSI 

Aspect% = SH50BSI 
ELSESI 

Aspect% = SHA0BSI 
END IFSI 
END IF1 
SI 

IFFFile$ = IFFFile$ + CHR$(0)SI 
Handles = xOpenS (SADD (IFFFile$) , 1006) SI 
IF Handles = THENSI 

Dialog$ = "Can't open the file you wanted! !! "SI 
GOTO EndSaveSI 
END IFSI 



' How many bytes contain IFF-Chunks ?SI 

BMHDSizeS = 20SI 

CMAPSizeS = MaxColour%*3 + ( (MaxColour%*3) AND 1 ) SI 

CAMGSizeS = 41 

BODYSizeS = (RasterW%/8) *RasterH%*RasterT%1 

' FORMsizeS = Chunk-Length + 8 Bytes per Chunk-Header 
Bytes ("ILBM")1 

FORMSizeS = BMHDSizeS+CMAPSizeS+CAMGSizeS+BODYSizeS+36 
1 

' FORM-Header 1 

Chunk$ = "FORM"1 

Lengths = xWriteS (Handles, SADD (Chunk$) , 4) 1 



115 



3. The Tracer Program Amiga 3D Graphic Programming 



Lengths = xWrite& (Handles, VARPTR (FORMSizeS) , 4) ? 

1 + ILBM for BitMap-File? 

Chunk$ = "ILBM"? 

Lengths = xWriteS (Handles, SADD (Chunk?) , 4) ? 

IF Lengths <= THEN? 

Dialog$ = "Write error on FORM-Header ! ! ! "? 

GOTO EndSave? 
END IF ? 

1 BMHD-Chunk ? 
Chunk$ = "BMHD"? 

Lengths = xWriteS (Handles, SADD (Chunk$) , 4) ? 
Lengths = xWriteS (Handles , VARPTR (BMHDSizeS ), 4) ? 
Lengths = xWriteS (Handles, VARPTR (RasterW%) , 2) ? 
Lengths = xWriteS (Handles, VARPTR (RasterH%) , 2) ? 
Lengths = xWriteS (Handles, VARPTR (Nulls ), 4) ? 
Temp% - (256 * RasterT%) ' No MASKING? 
Lengths - xWriteS (Handles, VARPTR (Temp%) , 2) ? 
Temp% =0 'No Packing? 

Lengths - xWriteS (Handles, VARPTR (Temp%) , 2) ? 
Temp% - 0? 

Lengths = xWriteS (Handles, VARPTR (Temp%) , 2) ? 
Lengths = xWriteS (Handles, VARPTR (Aspect%) , 2 ) ? 
Lengths = xWriteS (Handles, VARPTR (RasterW%) , 2) ? 
Lengths = xWriteS (Handles, VARPTR (RasterH%) , 2) ? 

IF Lengths <= THEN? 

Dialog$ = "Write error on BMHD-Chunk ! ! ! "? 

GOTO EndSave? 
END IF ? 

* CMAP-Chunk ? 

Chunk $ = "CMAP"? 

Lengths = xWriteS (Handles , SADD (Chunk?) , 4) ? 

Lengths -= xWriteS (Handles , VARPTR (CMAPSi zes ), 4 ) ? 

FOR i%=0 TO MaxColour%-l? 

Colours% = GetRGB4%(ColorMapS, i%)? 

blue - Colours% AND 15? 

Colours% = Coiours% - blue? 

green = (Colours%/16) AND 15? 

Colours! = Colours%-green*16? 

red = (Colours%/256) AND 15? 

POKE(ColorBuffer&+(i%*3) ) , red*16? 

POKE(ColorBufferS+(i%*3)+l),green*16 ? 

POKE(ColorBufferS+(i%*3)+2) ,blue*16? 
NEXT? 

Lengths = xWriteS (Handles, ColorBuf ferS, CMAPSizeS) ? 

IF Lengths <= THEN? 

Dialog$ = "Write error on CMAP-Chunk ! ! ! "? 

GOTO EndSave? 
END IF ? 

1 CAMG-Chunk ? 

Chunk$ = "CAMG"? 

Lengths = xWriteS (Handles, SADD (Chunk?) , 4) ? 

Lengths = xWriteS (Handles , VARPTR (CAMGSizeS ), 4) ? 

ModesS = PEEKW (Viewports + 32)? 

Lengths = xWriteS (Handles, VARPTR (ModesS ), 4) ? 



116 



Abacus 3.3 The Main Program 



IF Lengths <= THENfl 

Dialog$ = "Write error on CAMG-Chunk ! ! ! "f 

GOTO EndSavel 
END IF f 

' BODY-Chunk (BitMaps) 1 
Chunk$ = "BODY n, 5I 

Lengths - xWriteS (Handles, SADD (Chunk$) , 4) SI 
Lengths = xWriteS (Handles, VARPTR (BODYSizeS) , 4) II 
BytesPerRow% = RasterW%/81I 
FOR yl - TO RasterH%-11 
FOR b=0 TO RasterT%-15 

AdressS = BitPlanesS (b) + (yl*BytesPerRow%) SI 

Lengths = xWriteS (Handles, AdressS, BytesPerRow%) SI 

IF Lengths <= THEM 

Dialog$ = "Write error on BODY-Chunk ! ! ! "SI 
GOTO EndSavef 
END IF SI 
NEXTSI 
NEXTSI 
SI 

Dialog$ = "Saving OK"f 
SI 

EndSave:SI 

IF Handles <> THEN CALL xCloseS (Handles) 1 
IF Buffers <> THEN CALL FreeMemS (Buffers , Buffers i ze& ) Si 
CALL DialogBox (Dialog$, 1, True, xlb%, ylb%, x2b%, y2b%, False) SI 
CALL DoDialog(n%,l,-l,-l,-l,-l,xlb%,ylb%,x2b%,y2b%,-l,-l, - 
1,-D SI 
END IFfl 
CLS SI 

GOSUB MakeMenuSI 
RETURNS 
'SI 

Files created from this routine are not created in compressed form. More 
memory is required for saving an IFF file to disk, but IFF files save to 
disk 75% faster than normal files. 

We also thought about printed output. The following hardcopy routine 
sends the graphic on a printer. It uses the printer driver that was chosen 
from Preferences: 

HardCopy:! 

Status$ - " Status: Screen hardcopy"+CHR$ (0) f 

CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0)SI 
SI 

GOSUB DeleteMenuSI 
$ 

CALL DialogBox("No Printer", 0, True,xla%, yla%, x2a%, y2a%, Fal se) 
SI 

CALL DialogBox ("Printer 
OK",2,False,xlc%,ylc%,x2c%,y2c%,False)SI 

CALL DoDiaiog(n%,0,xla%,yla%,x2a%,ya2%, -1,-1,-1, - 
I,xlc%,ylc%,x2c%,y2c%) SI 

CLS SI 

IF n% <> THENSI 

Modes% = PEEKW (Viewports + 32) ^1 



117 



3. The Tracer Program Amiga 3D Graphic Programming 



sigBit% = AllocSignal% (-l)SI 

FlagsS = 655 3 7& ' MEMF_PUBLIC | MEMF_CLEARSI 

MsgPortS = AllocMem& (40,Flags&) SI 

IF MsgPort & = THENSI 

Dialog$ = "No 'MsgPort' ! ! ! "SI 

GOTO EndPrinter4SI 
END IFSI 

POKE(MsgPort& + 8) , 4 1 

POKE(MsgPort& + 9) , SI 

Nam$ = "PrtPort"+CHR$(0)SI 

POKEL (MsgP or t& + 10), SADD (Nam$ ) SI 

POKE(MsgPort& + 14), SI 

POKE(MsgPort& + 15), sigBit%SI 

SigTask& = FindTask& (0) SI 

POKEL (MsgPort & + 16), SigTask&l 

CALL AddPort (MsgPort&) ' lsit Port SI 

ioRequestS = AllocMemS {64, Flags& ) SI 
IF ioRequestS - THENSI 

Dialog$ = "No ioRequest ! ! ! "SI 

GOTO EndPrinter3SI 
END IFSI 

POKE (ioRequest & + 8), 5 SI 
POKE (ioRequest & + 9),0 SI 
POKEL (ioReque st & + 14), MsgPort&SI 



Nam$ = "printer. device"+CHR$ (0) 1 

PrinterErrorS = Ope nDev ice & (SADD (Nam$) , 0, ioRequest &, 0) SI 

IF PrinterErrorS <> THENSI 
Dialog$ = "No Printer ?!?"SI 
GOTO EndPrinter2SI 

END IFSI 
SI 

POKEW(i ©Requests + 28), 11 ' DumpRastport to 

Printer^ 

POKEL ( ioRequest & + 32), RastPortS ' Print entire screen SI 

POKEL (ioRequest& 

POKEL (ioReque st & 

POKEW(ioRequest& 

POKEW( ioRequest & 

POKEW(ioRequest& 

POKEW(ioRequest& 

POKEL (ioRequestS 

POKEL (ioRequestS 

POKEW(ioRequest& 
SI 

CALL 
DialogBox ("Printing. . . ", 1, False, xla%, yla%, x2a%, y2a%, False) 
SI 

PrinterErrorfi = DoIOS (ioRequest&) SI 

IF PrinterErrorS <> THENSI 

Dialog$ = "DumpRPort Error ="+STR$ (PrinterErrorS ) +" 
GOTO EndPrinterSI 

END IF! 
SI 

CLSSI 

Dialog$ = "Hardcopy done "SI 



118 



32), 


RastPortS 


36) , 


ColorMap&SI 


40), 


Mode s% SI 


44) , 


0SI 


46) , 


01 


48) , 


RasterW%SI 


50) , 


RasterH%SI 


52), 


0&SI 


56), 


o&si 


60), 


&H84SI 



Abacus 3.3 The Main Program 



EndPrinter: SI 

CALL CloseDevice (ioRequest&) SI 
SI 

EndPrinter2:SI 

POKE. (ioRequest& + 8), &HFFSI 
POKEL(ioRequest& + 20), -1SI 
POKEL(ioRequest& + 24), -1SI 
CALL FreeMemS (ioRequestfi, 64) SI 
SI 

EndPrinter3:SI 

CALL RemPort (MsgPort&)SI 
POKE (MsgPortS + 8), &HFF SI 
POKEL(MsgPort& + 20), -If 
CALL FreeSignal (sigBit%) SI 
CALL FreeMem& (MsgPortS, 40) SI 
SI 

EndPrinter4:SI 

CALL DialogBox (Dialog$, 1 , True, xlb% , ylb%, x2b% , y2b%, False) SI 
CALL DoDialog(n%,l,-i, -1,-1, -1 , xlb%, ylb%, x2b%, y2b%, -1,-1,- 
1,-1) SI 
END IFSI 
CLSSI 

GOSUB MakeMenu SI 
RE TURN SI 
'SI 

We included a routine to create a new background for the picture created 
by the tracer routine. This can give more realism to the picture than the 
usual background color does. This is done using the routines 

Background, Sky, Fhg (floating colors) and ScreenLoader. 

These routines allow you to choose between a simple pattern, a starry 
sky, a floating background that consists of a color and brightness 
change between colors, or an IFF picture that was created with a 
drawing program. 

Background: SI 

1 Background Determines! 

StatusS - " Status: Background selection"+CHR$ (0) SI 
CALL SetWindowTitles&(NWBase&,SADD(Status$) ,0)SI 
SI 

GOSUB DeleteMenuSI 
SI 

CALL DialogBox ("Pattern", 0, True,xla%, yla%,x2a%, y2a%, False) SI 
CALL DialogBox ("Load, 
screen", 2, False, xlb%,ylb%,x2b%,y2b%, False) SI 
SI 

CALL DoDialog(n%, f xla%,yla%, x2a%,y2a%, -1,-1,-1, - 
I,xlb%,ylb%,x2b%,y2b%) SI 

CLS SI 
SI 

IF n%=2 THENSI 

GOSUB ScreenLoaderSI 
Hg = True SI 
ELSESI 

CALL DialogBox ("Pattern", 0, True, xla%, yla%, x2a%, y2a%, False) SI 
CALL DialogBox ("Sky", 1, False, xlb%, ylb% , x2b%, y2b%, False) SI 
CALL 
DialogBox ( "Floating", 2 , False, xlc%, ylc% , x2c%, y2c%, False) SI 



119 



3. The Tracer Program Amiga 3D Graphic Programming 



CALL 
DoDialog(n%,0,xla%,yla%,x2a%,y2a%,xlb%,ylb%,x2b%,y2b%,xlc%,ylc% 
x2c%,y2c%) f 

CLSSI 

if n% = o then SI 
f 

CALL Printlt ("Background = Pattern", 40, False) SI 

SI 

LOCATE 10,11 

PRINT " Number of the pattern (0..34) : ";SI 

a = OSI 

CALL Formlnputlnt (Hx, 30 ! , ! , 34 ! ) 1 

Xpattern% = aSI 
SI 

LOCATE 11,1 SI 

PRINT " Foreground pen (APen) : ";SI 

a-APen%SI 

CALL Formlnputlnt (a, 30 ! , ! , CSNG (MaxColour%-l ) ) SI 

APen% = a SI 
SI 

LOCATE 12,1 SI 

PRINT " Background pen (BPeri) : ";SI 

a = BPen%SI 

CALL Formlnputlnt (a, 30 ! , ! , CSNG (MaxColour%-l) ) SI 

BPen% = a SI 
SI 

Xpattern% = Xpattern% MOD 
(NumberPatternS%+NumberPatternX%*2 + l)SI 
SI 

IF Xpattern% > NumberPatternS% THENSI 
CALL 
ExtendedFill (0, 0, RasterWl%, RasterHl%, PatternHX (Xpattern%- 
NumberPatternS%) , ! , 1 ! , APen%, BPen%) SI 
ELSE Si 
CALL 
bt anc^a rc*F i ± i \u f <j , Rasr.erWj.-b, RasterHj.T>, Pat ternliS (Nurnbe-rPat ternSij- 
Xpattern%),APen%,BPen%) SI 

END IF SI 

CLSSI 

Hg - TrueSI 
END IPS! 
SI 
IF n% = 1 THEN SI 

LOCATE 3,1 SI 

PRINT " Sky type: "SI 

PRINT " = Stars (scattered) "SI 

PRINT " 1 = Stars (centered) "SI 

PRINT " 2 - Lines (scattered) "SI 

PRINT " 3 = Lines (centered) "SI 

PRINT " 4 = Lines (middle centered) " SI 

SI 

LOCATE 10, If 

PRINT " Type : ";SI 

a ■= Art%SI 

CALL FormI nput I nt (a , 3 ! , ! , 4 ! ) SI 
Art% - aSI 
SI 

LOCATE 11,11 

PRINT " Color : ";SI 

a = 1SI 

CALL Formlnputlnt (a, 30 ! , ! , CSNG (MaxColour%-l ) ) SI 



120 



Abacus 3.3 The Main Program 



HColr% = al 

1 
LOCATE 12,15 
PRINT " Number : ";1 
a = 1001 

CALL Formlnputlnt (a, 30 ! , ! , 500 ! ) 1 
num% = al 
1 

CLS1 

CALL Sky (Art%, HColr%, num%) 1 
Hg = Truel 
END IF1 
1 

IF n% = 2 THENl 
CLSl 

1 
CALL Printlt ("Floating Background", 40, False) 1 
1 

LOCATE 10, If 

PRINT " from color: ";1 
Fl = 01 

CALL Formlnput (Fl, 30 ! , ! ,CSNG (MaxColour%-l) ) c 
Coloursl%=Fl1 
LOCATE 12,11 

PRINT " to color: ";1 
F2 = 11 

CALL Formlnput (F2, 30 ! , ! , CSNG (MaxColour%-l) ) < 
Colours2%=F21 
1 

CALL Fhg(Coloursl%,Colours2%)1 
Hg = Truel 
END IF1 
END IF1 
CLS 1 

GOSUB MakeMenul 
RETURN1 



SUB Fhg(Coloursl%,Colours2%) STATIC1 

SHARED RasterWl%, RasterHl%, Colour () , MaxColour%, WScreen&l 
SHARED NWBase&,RastPort&,OSSetPoint&,OSModus&,OSMaxColour&1 
1 Produce floating passage between Coloursl and Colours 1 
CALL Scronl 

1 
red.s=Colour (Coloursl%+l, 1) 1 
green. s=Colour (Coloursl%+l, 2)1 
blue . s-Colour (Coloursl %+l, 3) 1 
red.e=Colour (Colours2%+l, 1) 1 
green. e=Colour (Colours2%+l, 2) 1 
blue.e=Colour(Colours2%+l,3) 1 
1 

IF (PEEKW(OSModusS) AND &H800) = &H800 THEN ' HAM1 
1 

'Background limited to 16 Colors, or else Objects disturbed. 
1 

POKEW OSMaxColour&,161 
FOR y%=0 TO RasterHl%1 

red=red.s+ (y%/RasterHl%) * (red.e-red. s) 1 
green=green.s+ (y%/RasterHl%) * (green. e-green. s) 1 
blue=blue.s+ (y%/RasterHl%) * (blue. e-blue . s) 1 
' CALL SetPoint (0,y%, RasterWl.%, y%, red, green, blue) 1 



121 



3. The Tracer Program Amiga 3D Graphic Programming 



CALL 
OSSetPointS (0, y%, RasterWl%, y%, CLNG (1024*red) , CLNG (1024*green) , CL 
NG(1024*blue) ) ! 
NEXT y%! 

POKEW OSMaxColourS,64! 
ELSE! 

FOR y%=0 TO RasterHl%! 

red=red.s+ (y%/RasterHl%) * (red.e-red. s) ! 
green=green.s+ (y%/RasterHl%) * (green. e-green. s) ! 
blue=blue . s+ (y%/RasterHl% ) * (blue . e-blue . s ) ! 
■ CALL SetPoint (0, y%, RasterWl%, y%, red, green, blue) ! 

CALL 
OSSetPointS (0,y%, RasterWl%,y%, CLNG (1024*red) , CLNG (1024*green) , CL 
NG(1024*blue))! 
NEXT y%! 
END IF! 
CALL Scroff! 
END SUB! 
'! 

SUB Sky(a%,Col%,num%) STATIC! 

SHARED WScreenS,NWBaseS,RasterW%,RasterH%,RasterWl%! 
SHARED RasterHl%,RasterW2%,RasterH2%, RastPort &! 
CALL Scron! 

! 
CALL SetAPenS (RastPortS, Col%) ! 
CALL SetRastS (RastPortS, 0) ! 
! 

FOR n%=l TO num%! 
RANDOMIZE TIMERS 
! 

IF a%<4 THEN! 

IF a% AND 1 THEN! 

x%=RasterW2%+RasterW2%*RND*RND*SGN (RND-.5) ! 
y%=RasterH2%+RasterH2%*RND*RND*SGN(RND-.5)! 
ELSE! 

x%=RND*RasterWl%! 
y%=RND*RasterHl%! 
END IF! 
SI 

IF a% AND 2 THEN! 

IF x%=RasterW2% AND y%=RasterH2% THEN! 
dummy = WritePixel (RastPortS, x%, y%) ! 
ELSE! 

xl %= (x%-RasterW2% ) * . l+x%! 
yl%= (y%-RasterH2%) * . l+y%! 
IF xl%>=0 AND xl%<RasterW% AND yl%>=0 AND yl%<RasterH% 



THEN! 



CALL Moves (RastPortS , x%, y%) ! 
CALL Draws (RastPort S, xl%, yl%) ! 

END IF! 
END IF! 
ELSE! 

IF RND<.9 THEN! 

CALL WritePixelS (RastPortS, x%,y%) c 
ELSE! 

CALL Moves (RastPortS , x%-l, y%) ! 

CALL Draws (RastPortS, x%+l, y%) ! 

CALL Draws (RastPortS, x%,y%-l) ! 

CALL Draws (RastPortS, x%,y%+l) ! 
END IF! 
END IF! 



122 



Abacus 3.3 The Main Program 



ELSE! 
! 

x%=RND*RasterWl%! 
y%=RND*RasterHl%! 

CALL Moves (RastPortS,RasterW2%, RasterH2%) c 
CALL Draws (RastPort&,x%, y%) SI 
END IF! 
NEXT n%! 
! 

CALL SetAPenS (RastPortS , 1 ) SI 
SI 

CALL Scroff SI 
END SUBSI 



ScreenLoader : SI 
GOSUB Directory! 
SI 
Status$ = " Status: Screen Loader" + CHR$ (0) SI 
CALL SetWindowTitlesS (NWBaseS , SADD (Status$) , 0)! 
SI 

LOCATE 3,1 SI 

PRINT " Which IFF-File would you like to load? M SI 
PRINT SI 

PRINT " Filename : ";! 
IFFFile$ = ""! 
CALL FormlnputString (IFFFile$, 30 ! ) SI 

SI 
IF IFFFile$ <> "" THENSI 
SI 

BMHD = FalseSI 
CMAP = FalseSI 
CAMG = FalseSI 
Body = FalseSI 
SI 

Handle& = 01 
Buffers = 01 
SI 

1 reserve buffer! 

FlagsS = 65537& • MEMF_PUBLIC | MEMF_CLEAR! 

BufferSizeS = 360! 

Buffers = AllocMemS (BufferSizeS, FlagsS) ! 

IF Buffers = THEN! 

Dialog$ = "No more memory! ! !"! 
GOTO EndLoad! 
END IF! 
! 

InputBufferS = Buffers! 
ColorBufferS = Buffers + 120! 



IFFFile$ = IFFFile$ + CHR$(0)1 
Handles = xOpenS (SADD (IFFFile$) , 1005) ! 
IF Handles = THEN! 

Dialog$ = "IFF-File can not be opened!!! 1 

GOTO EndLoad! 
END IF! 



Lengths = xReadS (Handles, InputBufferS, 12) 1 

Chunk$ = ""! 

FOR n% = 8 TO 11! 



123 



3. The Tracer Program Amiga 3D Graphic Programming 



si 



Chunk$ - Chunk$ + CHR$ (PEEK (InputBuf ferS+n%) ) SI 
NEXTSI 

IF Chunk$ <> "ILBM" THEN SI 

Dialog$ = "Not IFF-Format ! ! ! "SI 
GOTO EndLoadSI 
END IFSI 
SI 

ReadLoop:SI 

Lengths = xReadS (Handles, InputBuf ferS, 8) SI 
ChunkwinlenS = PEEKL (InputBuf ferS + 4) SI 
Chunk$ - ""SI 
FOR n% = TO 3SI 

Chunk$ = Chunk$ + CHR$ (PEEK (InputBuf ferS+n%) ) SI 
NEXT SI 
SI 

IF Chunk$ = "BMHD" THEN ' BitMap-Header SI 
BMHD = TrueSI 

Lengths = xReadS (Handles, InputBuf ferS , ChunkwinlenS) SI 
RDepth% = PEEK (InputBuf fers + 8) SI 
Compression% = PEEK (InputBuf ferS + 10) SI 
RWidth% = PEEKW( InputBuf ferS + 16) SI 
RHeight% ' = PEEKW (InputBuf ferS + 18) SI 
BytesPerRow% = RWidth%/8SI 
RMaxColors% = 2 A (RDepth%) SI 
SI 

' IFF-Picture adapted to Display-Screen ?SI 
IF (RWidth% <> RasterW%) OR (RHeight% <> RasterH%) THENSI 
Dialog$ = "Format error: "+STR$ (RWidth%) +" 
x"+STR$ (RHeight%)SI 

GOTO EndLoadSI 
END IFSI 



SI 



ELSEIF Chunk$ = "CMAP" THEN ' Color-PaletteSI 

Lengths = xReadS (Handles, ColorBufferS , ChunkwinlenS) SI 

CMAP = TrueSI 

' Color-Palette set upSI 

FOR n% = TO RMaxColors% - 1SI 

red% - PEEK(ColorBufferS+(n%*3) ) /16SI 

green% = PEEK (ColorBuf ferS+ (n%*3) +1) /16SI 

blue% = PEEK(ColorBufferS+(n%*3)+2)/16SI 

dummy = SetRGB4 (Viewports, n%, red%, green%, blue%) SI 

SI 
POKEW OSColourS+n%*8 + 2, red%/15*1024SI 
POKEW OSColourS+n%*8+4, green%/15*1024SI 
POKEW OSColourS+n%*8+6, blue%/15*1024SI 

NEXTSI 

ELSEIF Chunk$ = "BODY" THEN 'BitMap LoaderSI 
CALL ScronSI 
Body = TrueSI 

IF Compression% = THEN 'No compressionSI 
FOR yl = TO RHeight% -1SI 
FOR b = TO RDepth% -1SI 
IF b<RasterT% THENSI 

AdressS = BitPlanesS (b) + (yl*BytesPerRow%) SI 
ELSESI 

AdressS = BufferSSI 
END IFSI 

Lengths = xReadS (Handles, AdressS , BytesPerRow% ) 
NEXTSI 
NEXTSI 



124 



Abacus 3.3 The Main Program 



ELSEIF Compression% = 1 THEN 'CmpByteRunl compression! 
FOR yl = TO RHeight% -If 
FOR b = TO RDepth% -1! 
IF b<RasterT% THEM 

AdressS = BitPlanesS (b) + (yl*BytesPerRow%) ! 
ELSE! 

AdressS = Buffers! 
END IF! 
NumBytes% = 0! 

! 
WHILE (NumBytes% < BytesPerRow%) ! 

Lengths = xReadS (Handles, InputBuf ferS, 1) ! 
Code% = PEEK(InputBufferS)! 

IF Code% < 128 THEN ' Code%-Bytes take over! 
Lengths = xReadS (Handles, AdressS + NumBytes%, 
Code%+l)! 

NumBytes% = NumBytes% + Code% + 1! 
ELSEIF Code% > 128 THEN ' Byte replicates! 
Lengths = xReadS (Handles, InputBuf ferS, 1) ! 
Byte% = PEEK(InputBufferS)! 
FOR n% = NumBytes% TO NumBytes% + 257 - Code%! 

POKE (AdressS+n%) ,Byte%! 
NEXT ! 

NumBytes% = NumBytes% + 257 - Code%! 
END IF! 
WEND! 
NEXT! 
NEXT! 

! 
ELSE! 

Dialog$ = "Unknown compression procedure!!!"! 
GOTO EndLoad! 
END IF! 
CALL Scroff! 
ELSE ! 

1 "Unknown" Chunk-Typ! 
FOR n = 1 TO ChunkwinlenS! 

Lengths = xReadS (Handles, InputBuf ferS, 1) ! 
NEXT! 

1 Chunks have even numnber of bytes! 
IF (ChunkwinlenS AND 1) = 1 THEN ! 

Lengths - xReadS (Handles, InputBufferS , 1 ) ! 
END IF! 
END IF! 
! 

' All Chunks read?! 

IF (BMHD = True) AND (CMAP = True) AND (Body = True) THEN! 

GOTO LoadOK! 
END IF! 
! 

1 Read ok, get next Chunk! 
IF Lengths > THEN GOTO ReadLoop! 
! 

IF Lengths < THEN ! 
Dialog$ = "Read error!!!"! 
GOTO EndLoad! 
END IF ! 
! 
IF (BMHD=False) OR (CMAP=False) OR (Body-0) THEN! 
Dialog$ = "Not all necessary ILBM-Chunks found!!!"! 
GOTO EndLoad! 



125 



3. The Tracer Program Amiga 3D Graphic Programming 



END IFSI 
SI 

LoadOK:1 

Dialog$ = "Loading OK"SI 
f 

EndLoad:! 

IF Handles <> THEN CALL xCloseS (Handles) SI 
IF Buffers <> THEN CALL FreeMemS (Buffers, Buff erSizeS) SI 
CALL DialogBox (Dialog$ , 1 , True, xlb%, ylb%, x2b% , y2b%, False) c 
CALL DoDialog(n%,l,-l,-l,-l,-l,xlb%,ylb%,x2b%,y2b%,-l,-l, 
1,-D SI 
END IFSI 
CLSSI 

GOSUB MakeMenuSI 
RETURNS 



The next routine (Info) tells you how many free and used elements 
(object definitions) there are in array K(). The routine named Help 
displays information on how to control the program from the keyboard. 
The menus include information about which keyboard shortcut can be 
used for which command: 

Info:SI 

' Information about free elements of K()SI 

Status$ = " Status: Info"+CHR$ (0) f 

CALL SetWindowTitlesS (NWBaseS , SADD (Status$) ,0)51 
SI 

GOSUB DeleteMenuSI 
SI 

CALL PrintIt("3D - CAD", 60, False) SI 

CALL Printlt ("Original-Version: Peter Schulz (c) 
1986",75,False)SI 

CALL Printlt ("Amiga-Version: Bruno Jennrich (c) 
1987", 90, False) SI 
SI 

a$ = "Maximum number of objects : "+STR$ (MaxNumber) SI 

CALL Printlt (a$, 105, False) SI 
1 

a$ - "Actual number of objects : "+STR$ (NumberK) SI 

CALL Printlt (a$, 120, False) SI 
1 

GOSUB PauseSI 
SI 

CLSSI 

GOSUB MakeMenuSI 
RETURNS 
'SI 
Help: SI 

' Which key press for which action! 

Status$ = " Status: Help"+CHR$ (0) SI 

CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0)1 
SI 

GOSUB DeleteMenuSI 
SI 

LOCATE 2,1 SI 
SI 

PRINT " P rojections point"SI 

PRINT " H Main point"SI 
SI 

PRINT " W enter angle"SI 



126 



Abacus 3.3 The Main Program 



PRIN'l " Cursor keys -> rotate'"?! 

PRINT " R ctate (SHIFT, CONTROL) "SI 
SI 

PRINT " D: spacing for main point "SI 

PRINT " +|-|* i/ Enlarge/reduce spacing (SHIFT* 1 -) "SI 
SI 

PRINT " V Enlarge" 1 ! 
SI 

PRINT " I, oad Object "SI 

PRINT " S ave Object"! 

PRINT " M erge Object." SI 

PRINT " N ew, clear all object s"SI 

PRINT " B Screen saver "SI 

PRINT " => Program end (Quit)" SI 
SI 

PRINT " Fl -> Editor load"! 
SI 

PRINT " F9 => Shadows initialization"^ 

PRINT " F10 -> Shadows "I 

PRINT " <SPACE> =■> Show picture" SI 

PRINT " C lear screen"; SI 
SI 

GOSUB PauseSI 

CLSSI 

GOSUB MakeMenuSI 
RETURNSI 
'SI 

Next is the routine used for enlargement or magnification of the screen 
image: 



In larger 



• Ql 



StatusS - " Status: Enlarge screen segment "+CHR$ (0) SI 
CALL SerWindowTitles^ (NWBase&, SADD (Status?) , ) SI 

GOSUB DeleteMenuSI 
SI 

CALL 
DialogBox ("Proportional", 0, True, xla%, yla%, x2a% , y2a%, False) SI 

CALL DialogBox ( "Distort ", 2, False, xlb%, ylb% , x2b% , y2b%, Fa 1 se) SI 

<n 

CALL DoD.ialog(n%, 0, xla%, yla%,x2a%, y2a%, xib%, ylb% , x2b%, y2b%, - 

1,-1, -1,-1) SI 

cm si 
si 

IF n%--0 THEN S! 
LOCATE 10,111 

PRINT " Enlargement Factor: ";SI 
a- IS! 

CALL Forminput (a, 30 : , . 1, 100 ! ) SI 

c: 

CLS ^ 

Picturewidth-a*FactorXSI 
Pictureheight=a*FactorYl 
? i c t u re x = R a s t e r W2 % / P i c t u r e w i d t h SI 
Picturey-^RasterH2%/PictureheightSI 
ELSESI 

Wait Fig! - FaiseSI 

GOSUB DrawNew^t 

CALL Rubber box (Sx%, Sy%, Widthe%, Heighte%, Fal se) SI 

Picturewidth- RasterW%/Widthe% * FactorXSI 



127 



3. The Tracer Program 



Amiga 3D Graphic Programming 



Pictureheight=RasterH%/Heighte% * FactorYl 
Picturex= (RasterW2%-Sx%) /FactorXl 
Picturey=(RasterH2%-Sy%) /FactorY SI 

END IF II 

Newone! = TrueSI 
WaitFlg! = TrueSI 
GOSUB DrawNewSI 
RETURNS 

PictureX and PictureY are recalculated for every enlargement 
(either proportional or distorted). 

Menu control of programs is the norm for Amiga applications. Almost 
every program in existence uses menus, so ours will too. This routine 
constructs and reads menus: 



MakeMenu:f 

Status? = " Status: Building menu"+CHR$ (0) SI 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0)SI 

SI 

MENU 1,0, 1, " Amiga'"!! 

MENU 1,1,1," 3D-Cad-Info I "SI 



MENU 2 
MENU 
MENU 
MENU 
MENU 
MENU 
MENU 
MENU 
MENU 
MENU 
MENU 



MENU 2 
MENU 2 
MENU 2 
K 
MENU 3,0 
MENU 3 

MENU 4,0 



MENU 
MENU 
MENU 
MENU 
MENU 
MENU 
MENU 



MENU 5,0 
MENU 5 
MENU 5 
MENU 5 
MENU 5 
MENU 5 



l,"File"fl 

1/1/ 

2,Start%, 

3,1, 

4/1/ 

5,0, 

6,1, 

7,0, 

8,Start%, 

9, Start%, 

10,Start%, 

-L -L , U , 

12,Start%, 

13,0, 

14,1, 



Load L"SI 

Save S"St 

Merge M"SI 

New N"SI 

M f 

Load material "SI 

__ u f 

Background "SI 
Save screen P"SI 
Hardcopy "SI 
..<][ 

Color palette C"SI 

_ ncj 

Program end Q"SI 



1, "Editor"SI 

1,1, " Load Editor 

Start%, "Parameter''^ 

l,Start%, 

2,Start%, 

3,Start%, 

4,Start%, 

5,0, 

6,Start%, 

7,Start%, 



A Fl"f 



Projection point P"SI 

Main point H"St 

a, _, c A"SI 

Distance D"SI 



' Enlarge 
Number corner 



Start%, "Draw" 



l,Start%, 

2,Start%, 

3,0, 

4,Start%, 

5,Start%, 



Shadows 
Initialization 



V"SI 

E"SI 



F10"SI 
F9 "SI 



Wire model 
Clear screen 



GOSUB NOOPSI 
CALL EmptyBuffersI 
RETURNS 



128 



Abacus 3.3 The Main Program 



MessageEvent : SI 

MTitle = MENU (0) SI 

MPoint = MENU (1) SI 

% 

IF MTitle <> THENSI 

SI 

IF MTitle = 1 THENSI 

IF MPoint = 1 THEN GOSUB InfoSI 
GOTO MessageEndeSI 
END IFSI 
f 
IF MTitle = 2 THENSI 

IF MPoint - 1 THEN GOSUB LoaderSI 
IF MPoint = 2 THEN GOSUB SaverSI 
IF MPoint = 3 THEN GOSUB MergerSI 
IF MPoint = 4 THEN GOSUB ArraylnitSI 

' Mpoint - 5 : " "SI 

IF MPoint - 6 THEN GOSUB LoadMatSI 

' MPoint = 7 : " "SI 

IF MPoint = 8 THEN GOSUB Background^ 
IF MPoint = 9 THEN GOSUB ScreenSaverSI 
IF MPoint = 10 THEN GOSUB HardCopySI 

' MPoint - 11 : " "SI 

IF MPoint = 12 THEN GOSUB ColorPaletteSI 

' MPoint = 13 : " "SI 

IF MPoint = 14 THEN GOSUB QuitSI 
GOTO MessageEndeSI 
END IFSI 
SI 
IF MTitle = 3 THENSI 

IF MPoint - 1 THEN GOSUB LoadEditorSI 
GOTO MessageEndeSI 
END IFSI 
SI 
IF MTitle = 4 THENSI 

IF MPoint = 1 THEN GOSUB InputPSI 
IF MPoint - 2 THEN GOSUB InputHSI 
IF MPoint = 3 THEN GOSUB InputAngleSI 
IF MPoint = 4 THEN GOSUB InputDPHSI 

' MPoint =5: " "SI 

IF MPoint = 6 THEN GOSUB Enlargement SI 
IF MPoint = 7 THEN GOSUB HowManyCornersSI 
GOTO MessageEndeSI 
END IFSI 
SI 

IF MTitle = 5 THENSI 

IF MPoint = 1 THEN GOSUB ShadowsSI 
IF MPoint = 2 THEN GOSUB InitParametersSI 
IF MPoint = 4 THEN GOSUB DrawNewSI 
IF MPoint = 5 THEN GOSUB ClearScreenSI 
END IFSI 
END IFSI 

MessageEnde: SI 
RETURNSI 
'SI 

When you select a menu item, all other menu items should be 
deactivated, to avoid accidentally choosing another menu item at the 
same time. The menu items are listed internally and deacitivated one 



129 



3. The Tracer Program Amiga 3D Graphic Programming 



after another — no item is skipped. When we turn the menus off, the 
program ignores any accidental menu item selections: 

DeleteMenu:1 

MENU 1,0,0, "Arniga"1 

MENU 2,0,0, "File"1 

MENU 3,0,0, "Editor "St 

MENU 4, 0,0, "Parameter "1 

MENU 5, 0,0, "Draw"1 
RETURNS 



When we want to go back to the main loop where the menu items 
appear, we must reactivate the menus (call MakeMenu). 

In addition to menu control, the program can accept keyboard shortcuts. 
Most menu items list these shortcuts in the right margin of the menu 
list. Because some functions can only be executed from the keyboard, 
we list the important shortcuts in the Help routine. You can access 
this routine by either pressing the <Help> key or the <?> key. Here is 
the routine which checks for a keypress: 



KeyEventrl 

Key$=INKEY$1 
IF Key$ <> "" 

LOCATE 1,11 


' THEN1 








T. 

1 
1 
THEN" 

1 
1 


F Start% = 
IF Key$ = 
IF Key$ = 


1 THEN1 
" " THEN 
"d" THEN 


GOSUB 
GOSUB 


DrawNewl 

InputDPHl 




IF Key$ = 


"c" THEN 


GOSUB 


ColorPalettel 




IF Key$ - 
I 

IF Key$ 
IF Key$ 
IF Key$ 
IF Key$ 


"*" OR Key$ - ' 

= " + " THEN D = 
= ""' , THEN D =- 
= "*" THEN D = 
- "/" THEN D =- 


"/" OR Key$ = " + " 

10 1 
-101 

1001 
-1001 


OR Key$ 


DPH = DPH + Dfl 
GOSUB Initiall 
Newone! = Truel 
WaitFlg! - Truel 
GOSUB DrawNewl 
END IF1 








<U 


IF Key$ = 
IF Key$ = 
IF Key$ = 
IF Key$ = 

IF Key$ = 


"v" THEN 
"p" THEN 
"h" THEN 
"a" THEN 
"e" THEN 


GOSUB 
GOSUB 

GOSUB 
GOSUB 
GOSUB 


Enlargement^ 

InputPl 

Input HI 

Input Angl el 

HowManyCornersI 




1 


IF Key$ = 


"c" THEN 


GOSUB 


ClearScreenl 




IF Key$ - 
IF Key$ = 


"s" THEN 
"b" THEN 


GOSUB 
GOSUB 


Saverl 
ScreenSaverl 





IF Key$ = CHR$(137) THEN GOSUB InitParametersI 
IF Key$ - CHR$(138) THEN GOSUB Shadows^ 



130 



Abacus 3.3 The Main Program 



IF (Key$ = CHR$(28)) OR (Key$ - CHR$(29)) OR (Key$ = 
CHR$(30)) OR (Key$ = CHR$(31)) THEN5 
IF Key$ = CHR$(28) THEN5 

Beta = Beta + Pi/155 
END IF 5 
IF Key$ = CHR$ (29) THEN5 

Beta = Beta - Pi/155 
END IF 5 

IF Key$ = CHR$(30) THEN5 
Alpha = Alpha + Pi/155 
END IF 5 

IF Key$ = CHR$(31) THEN5 
Alpha = Alpha - Pi/155 
END IF5 

GOSUB Initials 
Newone! = True5 
WaitFlg! = True5 
GOSUB DrawNew5 
END IF5 
5 

IF (Key$ = CHR$ (18) ) OR (Key$ = "R") THEN5 
IF Key$ = CHR$(18) THEN ,/N R5 

Gamma = Gamma + Pi/155 
END IF 5 
IF Key$ = "R" THEN5 

Gamma = Gamma - Pi/155 
END IF5 

GOSUB Initials 
Newone ! = True5 
WaitFlg! = True5 
GOSUB DrawNew5 
END IF 5 
END IF5 

IF Key$ = "m" THEN GOSUB Merger5 
IF Key$ - "n" THEN GOSUB Arraylnit 5 
IF Key$ = "1" THEN GOSUB Loader 5 

IF Key$ - "?" OR Key$ = CHR$(139) THEN GOSUB Help5 
IF Key$ = "q" THEN Quit5 
IF Key$ = "i" THEN GOSUB Info5 
5 

IF Key$ = CHR$(1) THEN GOSUB LoadEditor5 
END IF 5 
RETURN5 



No operations are performed when the program is waiting for user 
input, or when it isn't executing any shadow calculations. This is 
known as NOP (No Operation) status. This status appears in the top 
window line through the NOOP routine: 

NOOP: 5 

Status$ = " Status: NOP"+CHR$ (0) 5 

CALL SetWindowTitles&(NWBase&,SADD(Status$) ,0)5 

RETURN5 



The following routines allow the creation and control of requesters. 
These are contained in DialogBox, which draws the requester, and 
DoDialog, which waits for you to select a requester gadget: 



131 



3. The Tracer Program Amiga 3D Graphic Programming 



SUB DialogBox (Dialog$,Position%, Ret, xl%,yl%, x2%,y2%, Scr) STATIC^ 
SHARED RastPort&,NRastPort&,True,RasterWl%,RasterW2%SI 
1 Create your ownrequ requester^ 
1 Dialog$ = Text in Dialog BoxSI 
1 Position% SI 
1 - rights 
1 1 = centerSI 

2 = left SI 
1 Ret% = can you press <Return>?SI 
1 True = YesSI 
1 False = NoSI 

' xl%,yl%,x2%,yl% = Size of ' click ' -Field (word returned) SI 
1 Scr = In which screen output ?SI 
1 True = Display-ScreenSI 
1 False = User-ScreenSI 
SI 
IF Scr - True THENSI 
rp& = RastPort&SI 
Middles = RasterW2%SI 
SEnd& = RasterWl%SI 
1 Write to Display-ScreenSI 
ELSESI 

rp& = NRastPort&SI 
Middles = 3201 
SEnd& = 6401 

1 RastPort des Basic Windows*! 
END IFSI 
SI 

yl% = 150SI 
y2% = 150 + 6 + 10SI 
SI 

Lengths = TextLength& (rp&, SADD (Dialog$) , LEN (Dialog$) ) SI 
SI 

IF Position! = THEN SI 
xl% = 70SI 

x2% = xi% + Lengths + 20Tl 
END IFSI 
SI 

IF Position! - 1 THENSI 

xl% = Middle&-Length&/2-10SI 
x2% = Middle&+Length&/2+10SI 
END IFSI 
SI 

IF Position! = 2 THEN SI 

xl% = SEnd&-70-20-10-Length&SI 
x2% = SEnd&-70-10SI 
END IFSI 
SI 

CALL Moves (rp&,xl% + 10,yl% + 10) SI 
CALL Text& (rp&, SADD (Dialog$) , LEN (Dialog$) ) SI 
SI 

IF Scr = True THENSI 

CALL Box(rp&,xl%,yl%,x2%,y2%)SI 
CALL Box(rp&,xl%-4,yl%-2,x2%+4,y2%+2)SI 

IF Ret = True THEN CALL Box (rp& , xl%-2, yl%-l , x2% + 2, y 2% + 1 ) SI 
ELSESI 

LINE (xl%,yl%)-(x2%,y2%), ,bSI 
LINE (xl%-2,yl%-2)-(x2%+2,y2%+2) , ,bSI 

IF Ret = True THEN LINE (xl%-l, yl%-l) - (x2% + l ,y2% + l) , ,M 
END IFSI 
END SUBSI 



132 



Abacus 3.3 The Main Program 



SUB DoDialog(n%,Ret%,xla%,yla%,x2a%,y2a%,xlb%,ylb%,x2b%, 
y2b%,xlc%,ylc%,x2c%,y2c%) STATIC! 
* Dialog boxen read! 
1 n%: which gadget clicked ?! 

1 Ret%: which gadget specified by pressing <Return>?! 
' xl . , yl . , x2 . , y2 . coordinates ofthe box! 
CALL EmptyBuffers! 
n% = -1! 
WHILE (n% = -1)1 

IF MOUSE (0) <> THEN! 
x = MOUSE (1)1 
y = MOUSE (2)1 
! 

IF (xla%<x) AND (x2a%>x) AND (yla%<y) AND (y2a%>y) THEN n% 
= 0! 

IF (xlb%<x) AND (x2b%>x) AND (ylb%<y) AND (y2b%>y) THEN n% 

IF (xlc%<x) AND (x2c%>x) AND (ylc%<y) AND (y2c%>y) THEN n% 



1 1 
21 



END IF! 

IF INKEY$ = CHR$(13) THEN n% = Ret%! 
WEND! 
END SUB! 



The Print It routine displays centered text: 

SUB Printlt (Out$,y%, Scr) STATIC! 

SHARED RastPortS, NRastPortS,RasterW2%, True, Lengths! 
' Centered text output on one of the two screens 1 
' Out$: Printed string! 
' y%: verticle Position ?! 
1 Scr: User or Display Screen?! 
IF Scr = True THEN! 

rpS = RastPortS! 

Middles = RasterW2%! 

1 write to new (Display) Screen! 
ELSE! 

rpS = NRastPorts! 

Middles = 320 ' User-Screen (NO OP Window)! 
END IF! 

Lengths = TextLengthS (rpS, SADD (Out$) , LEN (Out$) ) ! 
Middles = Middles - Lengths /2! 
CALL Moves (rpS, Middles, CLNG (y%) ) ! 
CALL Texts (rpS, SADD (Out$) , LEN (Out $)) ! 
END SUB! 
'! 

The text is centered on the screen. This is especially useful for the 
information lines that appear inside requesters. 

The Box routine draws a box around requesters, while the Rubber Box 
routine keeps mouse movement within this requester: 

SUB Box(RastPortS,xl%,yl%,x2%,y2%) STATIC! 
1 rectangle in Display-Screen! 
1 RastPortS: draw in which RastPort ! 
1 xl,yl,x2,y2 coordinaten ofthe rectangle! 
CALL Moves (RastPortS, xl%,yl%)! 
CALL Draws (RastPortS, x2%,yl%)! 
CALL Draws (RastPortS, x2%,y2%)! 



133 



3. The Tracer Program Amiga 3D Graphic Programming 



CALL Draws (RastPortS, xl%,y2%)l 

CALL Draws (RastPortS ,xl%,yl%+l) 1 
END SIM 
'SI 

SUB Rubberbox( x%, y%, w%, h%, Back!) STATIC! 
SHARED RasterWl%,RasterHl%,WScreenS,NRastPortS, RastPortS, 
NWScreenS,NWBaseS,WBaseS, Lengths, True, False! 

1 Make rectangle with mouse! 

' x%,y%: upper left corner*! 

1 w%,h%: Width, Height! 

1 Back! : Return touser window ?! 

CALL Scroll 

CALL SetDrMdS (RastPortS , 2) 'COMPLEMENT ! 

! 

CALL SetAPenS (RastPortS , 1 ) 1 
1 
Repitition:! 

Oldx% = If 

OldY% = 1! 

Flag! = 01 



1 



CALL EmptyBuffers! 

mousel : ! 
x% = PEEKW(WScreenS+18)l 
y% = PEEKW(WScreenS+16)l 

IF (x% <> Oldx%) OR (y%OOldY%) THEN! 
IF Flag! = 1 THEN 1 

CALL Move& (RastPortS , 01dx%, 0)1 
CALL Draws (RastPortS, Oldx%, RasterHl%) SI 
CALL Moves (RastPortS, 0,OldY%) SI 
CALL Draws {RastPortS, RasterWl%, 01 dY%) SI 
END IFSI 

Flag! = 11 

CALL Moves (RastPortS, x%, 0) 1 
CALL Draws (RastPortS, x%, RasterHl%) 1 
CALL Moves (RastPortS, 0,y%) 1 
CALL Draws (RastPortS, RasterWl%,y%) 1 
01dx% = x%l 
OldY% = y%l 
END IF 1 

IF MOUSE (0) = GOTO mousel 1 

CALL Moves (RastPortS, x%, 0)1 

CALL Draws (RastPortS, x%, RasterHl%) 1 

CALL Moves (RastPortS, 0,y%)l 

CALL Draws (RastPortS, RasterWl%, y%) 1 

1 
Oldx% = -11 
OldY% = -11 
Flag! = 01 
1 
WHILE MOUSE (0) <> 01 
1 

w% = PEEKW(WScreenS+18)l 

h% = PEEKW(WScreenS+16)l 

IF (w% <> 01dx%) OR (h% <> OldY%) THEN! 



134 



Abacus 3.3 The Main Program 



IF Flag! = 1 THEN CALL Box (RastPortiS, x%, y%, Oldx%, QldY%) 1 
Flag: = 11 
1 

IF (w% < x% + 6) THEN w% = x% + 61 
IF (h% < y%- ; 3) THEN h% = y%+31 
1 

IF (w% > x%) AND (h% > y%) THEN1 

IF w%>RasterWl% THEN w% = RasterWl%1 
IF h%>RasterHl% THEN h% = RasterHl%1 
Oldx% = w%1 
OldY% = h%1 
1 
CALL Box(RasT;Port&,x%,y%,w%,h%) 1 
END IF 1 

END IFl 
WEND 1 
1 

IF Flag - 1 THEN CALL Box (RastPartS, x%, y%, w%, h%) 1 

1 
CALL Printlt ("Section Ok ?", 130, True) 1 
1 

Flag! = 01 
Oldx% = -11 
OldY% = -11 
1 

CALL DialogBox("OK",l,True,xla%,yla%,x2a%,y2a%,True)1 
1 

CALL EmptyBuffersI 
1 

a$ = ""1 

WHILE (MOUSE (0) = 0) AND (a$ <> CHR$(13)) 1 

a$ - INKEY31 
WEND1 
1 

Mx% = PEEKW(WScreen&+18)1 
My% =■ PEEKW(WScreen& + 16)1 
1 

Try Again = Truel 

IF (Mx%>xla%) AND (Mx%<x2a%) AND (My%>yla%) AND (My%<y2a%) 
THEN TryAgain = Falsel 

IF a$ - CHR$(13) THEN TryAgain = Falsel 
1 

CALL Printlt ("Section Ok ?", 130, True) 1 
1 
CALL DialogBox ("OK", 1, True, xla%,yla%,x2a%,y2a%, True) 1 
1 

IF TryAgain = True THEN GOTO Repitition 1 
1 

w% = w%-x%1 
h% - h%-y% 1 
1 

CALL SetDrMdS (RastPort&, 1) ' JAM21 
CALL SetDrMd&(NRastPort&,l)f 
1 

IF Back! - True THEN CALL Scroffl 
END SUB1 



We have used our own Box routine instead of the LINE statement. 
This allows us to display requesters in both the display screen and the 
user screen. We can't use LINE in this case because we are accessing 



135 



3. The Tracer Program Amiga 3D Graphic Programming 



and changing the display screen using Rastport, which allows us to 
access the entire bitmap. We can also use the points that normally draw 
the border around a window or screen. This allows us to draw on the 
full screen. 

The Pause routine waits for the user to press either a mouse button or 
a key. 

We must make sure that the mouse and keyboard buffers are empty. So 
all the keypresses before the check are ignored and it can react to the 
new keypresses: 

Pause: SI 

1 Wait for (Mouse-) key pressSI 

CALL EmptyBuffers ' clear buffer SI 

WHILE (INKEY$ = "") AND (MOUSE (0) = 0)1 

WENDSI 
RETURNS 



SUB EmptyBuffers STATICSI 

1 clear mouse and keyboard buffer SI 

WHILE MOUSE (0) <> Of 

WEND 5 

WHILE (INKEY$<>"")SI 

WENDSI 
END SUBSI 

•si 

The following routines implement a completely different kind of input: 

SUB Formlnput (i, winlen, unt ! , ob! ) STATICSI 

'Enter indivudal real values! 

' i => number variables to be real (old value 

displayed) SI 

'winlen, unt !, ob! => see above. SI 

z=CSRLINSI 

s=POS(0)SI 

a$ = " "SI 

CALL PutReal (i , z, s, winlen) SI 

CALL GetReal (i , a$, z, s, wi nlen, unt ! , ob! ) SI 
END SUBSI 
'SI 

SUB Formlnputlnt (i, winlen, unt !, ob! ) STATICSI 
'Enter an indivudal integer value! 

' i => number variavles to be read (old value 

displayed) SI 
'winlen, unt! ,ob! => see above. SI 

z=CSRLINSI 

s=POS(0)SI 

a$ - " "SI 

CALL PutReal (i , z, s, winlen) SI 

CALL Getlnt (i, a$, z, s, winlen, unt !, ob! ) SI 
END SUBSI 
'SI 

SUB FormlnputString (s$, winlen) STATICSI 
' String read (z.B. Filename)SI 

a$ = " "SI 

s = POS(0) SI 



136 



Abacus 3.3 The Main Program 



z = CSRLINSI 

CALL PutString (s$, z, s, winlen) SI 

CALL Get St ring 
(s$,a$, "abcdefghi jklmnopqrstuvwxyzdv |_ABCDEFGHIJKLMNOPQRSTUVWXYZ 
DV\12345678 90.-_:/",z,s,winlen)SI 
END SUBSI 



These routines waits for the input of a real number, an integer value or 
a character string. The input routines of the editor are used for this. 

Illegal characters (e.g., letters entered when numbers should be entered) 
are ignored. When we enter a value smaller than the given lower limit 
or larger than the upper limit, the screen flashes, to indicate an error. 

All disk operations can either use the current subdirectory or change to 
a new one. The Directory routine makes this possible: 

Directory -.SI 

' Directory read, or change driveSI 

Status$ = " Status: Directory"+CHR$ (0) <ff 

CALL SetWindowTitlesS (NWBaseS , SADD (Status$) ,0) SI 

\ 

GOSUB DeleteMenuSI 

a$ = "Active Directory: "+ActDrive$SI 

CALL Printlt (a$, 50, False) SI 

CHDIR ActDrive$SI 

SI 

RepeatD:SI 

CALL DialogBox("Files", 0, False, xla%, yla%, x2a%, y2a%, False) SI 
CALL DialogBox ("Load", 1, True, xlb%, ylb%, x2b%, y2b%, False) SI 
CALL DialogBox ("Chdir", 2, False, xlc%, ylc%, x2c%, y2c%, False) SI 
\ 

CALL 
DoDialog (n%, i, xla%, yla%, x2a%, y2a%, xlb%, ylb%, x2b%, y2b%, xlc%, ylc%, 
x2c%,y2c%) SI 
\ 

CLSSI 

IF n% = THEM 
FILESSI 
GOSUB Paused 
CLSSI 

GOTO RepeatDSI 
END IFSI 
IF n% = 2 THEM. 

a$ = "Active Directory: " +Act Drive $f 
CALL Printlt (a$, 50, False) SI 
SI 

LOCATE 10,1SI 

PRINT " New Directory: ";SI 

CALL FormlnputString (ActDrive$, 30 ! ) SI 
SI 

CHDIR ActDrive$SI 
SI 
CLSSI 

GOTO RepeatDSI 
END IF SI 
CLSSI 
RETURNSI 



137 



3, The Tracer Program Amiga 3D Graphic Programming 



Selecting a new disk directory makes it possible to use other disks. 
You may know the dilemma of suddenly having to make a disk swap 
(maybe because of a read error), but a chdir or cd can't be executed 
from the program. Sometimes data loss can occur. Not with our 
program: You can use a new disk by calling Directory without 
quitting the program. 

When you want to leave the program, Quit is called. This routine 
asks you if you want to quit the program and gives you a chance to 
respond. If you exit the program, it releases all the memory it has 
occupied and closes all of the libraries and the newly opened display 
screen: 

Closelt:^ 

' Close all and free memory^ 

GOSUB CloseGfxl 

WINDOW CLOSE 2 SI 

SCREEN CLOSE 1 ' automatic release of allocated 6th bit ma pi 

MENU RESET • f 
<5 

"IF SetPointAdr& <> THEN CALL 
FreeMemfc (SetPointAdrs, SetPointNumfc) Ti 

IF PatternSS <> THEN CALL 
FreeMemS (PatternSfi, (NumberPatternS% + l) *2*16) <il 

IF PatternXS <> C THEN CALL 
FreeMemfi (PatternX&, (NumberPatternX%*2+ 1 ) *2*16) Ti 
'Save pattern and release ASSEM-Rour.inoSI 

LIBRARY CLOSED 
RETURNS 

1 

Quitifl 

CALL ScroffSI 

StatusS = " Program, end ?" fCHR$ (0) 11 

CALL SetWindowTitles& (NWBaseS , SADD (Status$) , ) f 

GOSUB DeleteMenuf 
H 

CALL PrintIt("Do you really wish to exit the 
program?", 100, False) 1 
1 

CALL DialogBox ("No", 0, True, xla%, yla%, x2a%, y2a%, Fal se) f 
CALL DialogBox ("New start", 1 , False, xib%, ylb% , x2b%, y2b%, False) <fl 
CALL DialogBox ("Yes" , 2, False, xl c% . vlc%, x2c%, v2c%, False) \ 
\ 

CALL 
DoDialog(n%,0,xla%,yla%,x2a%,y2a%,xlb%,ylb%,x2b%,y2b%,xlc%,ylc%, 
x2c%,y2c%) \ 
% 

CLSSI 

IF n% > THENf 
GOSUB Closeltfl 
IF n% -■= 1 THENH 

RUN \ 
ELSE1 

END11 
END IF<R 
END IFf 
GOSUB MakeMenuH 



138 



Abacus 3.3 The Main Program 



RETURNS 
'SI 

This routine allows you to restart the program instead of ending the 
program. 

The Scron and Scrof f routines switch between the new display 
screen and the user screen. To erase the display screen (e.g., before 
redrawing a wire model) Scree nErase is called: 

SUB Scroff STATIC^ 
SHARED NWBase&,NWScreen&SI 

' Display Screen off , User Screen onSI 

CALL ScreenToFrontS (NWScreen&) SI 

WINDOW OUTPUT 1SI 

WINDOW 11 

CALL ActivateWindowS (NWBase&) SI 
END SUBSI 
'I 

SUB Scron STATICSI 
SHARED WScreen&,WBase&SI 

1 Display Screen on, User Screen offSI 

CALL ScreenToFront& (WScreen&) SI 

WINDOW OUTPUT 2f 

WINDOW 2SI 

CALL ActivateWindowS (WBaseS) SI 
END SUBSI 



ClearScreen:SI 

Status$ = " Status: Clear screen"+CHR$ (0) SI 

CALL SetWindowTitlesS (NWBaseS , SADD (Status$) , 0)< 

SI 

CALL SetRastS (RastPort&, 0) SI 

Hg = TrueSI 

SI 

GOSUB NOOPSI 
RETURNSI 



You have the option of calling the object editor with LoadEditor: 

LoadEditor:SI 

Status$ = " Status: Editor loading"+CHR$ (0) SI 

CALL SetWindowTitles&(NWBase&,SADD(Status$) ,0)SI 
SI 

GOSUB DeleteMenuSI 
SI 

CALL DialogBox("not called", 0, True, xla%, yla%, x2a%, y2a%, False) 
SI 

CALL DialogBox ("called", 2, False, xlc%, ylc%, x2c%, y2c%, False) SI 

CALL DoDialog (n%, 0, xla%,yla%, x2a%,ya2%, -1,-1,-1, - 
I,xlc%,ylc%,x2c%,y2c%) SI 

CLSSI 

IF n% = 2 THENSI 

CHDIR "Tracer:" SI 
GOSUB CloseltSI 
CHAIN "Editor"SI 

END IFSI 

GOSUB MakeMenu SI 



139 



3. The Tracer Program Amiga 3D Graphic Programming 



ENDSI 

ErrorHandling keeps you informed of errors encountered. These 
can only be I/O (input/output) errors (e.g., a read/write error on the 
disk). If another error is encountered in your program, the editor 
displays the error number (e.g., 2 [Syntax error]). See Appendix B of 
your AmigaBASIC manual, or Appendix A of Abacus' 
AmigaBASIC Inside and Out for a list of error messages and 
numbers: 

ErrorHandling: SI 
NumErr = ERRSI 
1 

Status$ = " Status: Next Big Error ! ! ! "+CHR$ (0) f 
CALL SetWindowTitles&(NWBase&,SADD(Status$) , 0)SI 
SI 

GOSUB DeleteMenuSI 
SI 

Dialog$ = ""SI 
IF NumErr = 64 THEN ' Bad File ModeSI 

Dialog$ = "Bad file name ! ! ! "SI 
END IFSI 
SI 
IF NumErr = 57 THEN ' Device I/O ErrorSI 

Dialog$ = "Device I/O Error ! ! ! "SI 
END IFSI 
SI 
IF NumErr - 68 THEN ' Device unableSI 

Dialog$ = "Device not found"SI 
END IFSI 
SI 
IF NumErr = 61 THEN ' Disk FullSI 

Dialog$ - "Diskette is full ! ! ! " SI 
END IFSI 
SI 
IF NumErr = 53 THEN • File not foundSI 

Dialog$ = "File not found! !! "SI 
END IFSI 
SI 
IF NumErr = 70 THEN ' Permission deniedSI 

Dialog$ = "Permission denied! !! "SI 
END IFSI 
SI 
IF Dialog$ = "" THENSI 

Dialog$ = "Error Number = "+STR$ (NumErr) SI 
END IFSI 
SI " 

CALL DialogBox(Dialog$, I, True, xla%, yla%, x2a%, y2a%, False) SI 
SI 

CALL DoDialog (n%, 1,-1, -1,-1,-1, xla%, yla%, x2a%, y2a%, -1,-1,-1, - 
DSI 
SI 

CLSSI 

GOSUB MakeMenuSI 
RESUME ok SI 
RETURNSI 



140 



Abacus 3.3 The Main Program 



3.3.2 Merging Tracer Modules into one Program 



This explains all of the routines used in our tracer program. These 
routines are completely listed in the appendices and are contained on the 
optional disk in seven separate modules. This makes merging and 
adapting them to your own programs much easier. 

Note: If you type in these modules yourself, here are a few ground rules 

which you must follow to complete the tracer program: 

Name the disk to which you are saving the files tracer : and 
create a directory called modules. 

Do not type the seven tracer modules in as one program. These 
seven modules must be entered separately and merged together as 
explained below. This method allows easy incorporation of these 
codes into other programs later on. 

Enter each module from AmigaBASIC and save each module in 
ASCII format under the exact name given in the appendices, in a 
directory named modules. For example, the first module must 
be saved as follows: 

save "tracer .'modules /in it . asc", a 

Now that you've seen all of the routines used in the tracer, we must 
combine the program modules (which are saved as ASCII files) into 
one program on disk. 

Run AmigaBASIC and enter the following in the BASIC window: 

clear ,140000 

This reserves the necessary program memory (this command must be 
executed before each start of the tracer). This release only works on 
Amigas with at least 512K of RAM. 

The optional disk (named tracer) has all of the modules in a 
directory called modules, so set the current directory to 
tracer : modules using the following AmigaBASIC command 
sequence: 

chdir "tracer :modules" 



141 



3. The Tracer Program Amiga 3D Graphic Programming 



Note: If you're using a backup copy of the optional disk, or you're using a 

disk that you named yourself, rename your disk to tracer. 

Now we will combine the tracer modules found in the modules 
directory. Merge them using the following commands in direct mode 
(enter them in the BASIC window): 

merge "Init.asc" 

merge "System. asc" 

merge "Wiremodel-draw . asc" 

merge "Wiremodel-input . asc" 

merge "Shadow-init . asc" 

merge "Shadowing . asc" 

merge "Service . asc" 

Then the completed program should be saved as described below: 

save "tracer .-tracer" 

You can save this program to the optional disk or to your own disk. 

Note : Your own disk must have the name t racer for the tracer program to 

work correctly. 

The tracer program, the editor program, and the machine language 
routine SetPoint.B must be available in the main directory of the 
disk. The SetPoint.B routine is described in Appendix D, which 
includes the source code and a BASIC loader. 

You must ensure that the .bmap files are also on the disk, since the 
program uses dos. bmap, exec. bmap, graphics. bmap, and 
intuition .bmap libraries. These files are iocated in the libs 
directory of the optional disk. If you're using your own disk, you may 
have to create these libraries using the FDConvert program on your 
Extras disk. 

The easiest procedure is to copy the entire disk with the Diskcopy 
command. After merging the individual modules you can erase these 
from the modules directory to get more room on the disk. Do this 
with the copy of the disk only, and not with the original disk! After 
saving the complete tracer the entire program is on the disk. You're 
ready to go into 3D mode. 



142 



4. 
Using the Program 



Abacus 4. Using the Program 



4 . Using the Program 



In our exploration of the program modules in Chapter Three, we didn't 
talk at all about operating the finished product. This chapter is a set of 
operating instructions for the tracer and editor programs. 



4.1 Editor Documentation 



4.1.1 Input — General Information 



All input occurs in the windows. Input can be edited with the cursor 
keys, <Delete> and <Backspace> keys when input mode is active inside 
of the editor's main window. When input extends past the window, the 
window scrolls to the left and the characters at the beginning of the line 
scroll off the screen. The <Cursor left> and <Cursor right> keys let the 
visible section be accessible. It is important to note that only certain 
keys are accepted for certain prompts: 

a) integer values: — 9,- 

b) real values: 0,1, ..,9,-,. 

c) vectors: 0,1, ..,9,-,.,"," 

d) character strings: all characters 

e) single characters: 
for visible input: y,n 

for enlargement, rotation, movement: q,c,d 
for the Show function: d,m,f 

Each input can be ended by pressing the <Return> key, regardless of 
the cursor location. You must press <Return> after characters because 
the program waits for the first valid key. For values greater than zero 
and less than one, a zero must precede the decimal point (e.g., 0.6 is 
acceptable, while .6 results in an error). If the user enters an input in an 
invalid form, or if the value entered lies outside the specified value 
range, the program ignores the input and returns the cursor to the 
beginning of the line for correction. Valid values are in the range [- 
10000..+ 10000], with the following four exceptions: 



145 



4. Using the Program Amiga 3D Graphic Programming 



a) 


material type: 


1.. 10000 


b) 


inner or outer radius: 


0..1 


c) 


enlargement factor: 


1 164. .64 


$ 


line view: 


1..50 



When a coordinate vector is required in an input position, which is 
always the case for us, you have two input options: conventional 
keyboard input or mouse input. When you use the mouse, the cursor 
must be at the beginning of the corresponding line — no valid keys can 
be pressed for this input. When using the mouse, the desired position 
in the window can be clicked on where the coordinates will be displayed 
in the input and output windows. When it is in the position you want, 
all you need to do is press <Return>. Then the mouse position in the 
input line takes charge, either directly or as the difference between the 
mouse vector and the direction vector. 

There are some special cases to be aware of in menu input. For 
example, if you decide that there is an input error in the fifth input 
position, you don't need to start again. Instead you can return to the 
incorrect line. This is done with the <Cursor up> key. This is only 
active when no keys are pressed in the input line. You don't have to 
enter the entire line. Simply move the cursor to the error, correct it and 
press the <Return> key. Then move down to the old input line with 
the <Cursor down> key. 



4.1.2 Entering Object Data 



When the above program specifications for input are considered, 
entering object data is no longer a problem. You know which data is 
actually checked and how the input of a certain object is started. The 
information about the first point can be taken from the drawings below. 

The last point is easy: All the predefined objects can be found under the 
Body menu item. When you want to enter a certain object from this 
list, you only need to choose it from the list, A new data set appears in 
the editor window and the cursor moves to the first position. The input 
can then begin. The object data is checked to see if the given object 
should be visible on the screen, and which material should be assigned 
to it. The materials can differ in color, shade intensity, and reflection 
factor, which are represented by numbers. The material belonging to 
this number is entered with the material editor, which is described in 
the next section. The following pictures show the simpler types of 
objects that can be entered. 



146 



Abacus 



4.1 Editor Documentation 



Plane 

M 0, 0, 10 

A 10, 0, 

B 0, 10, 




Triangle 

M 10, 10, 

A 10, 0, 

B 10, 10, 




Figure 4.1 



147 



4. Using the Program 



Amiga 3D Graphic Programming 



i Parallelogram 




M 10, 


10, 







A 10, 


o, 







B 10, 


10, 









B 




y 








A 


\/[/ 









tircie 

M 10 r 10, 

A 10, 0, 

B 0, 10, 




Figure 4.2 



148 



Abacus 



4.1 Editor Documentation 



Circular segment 



M 10, 10, 
A 10, 0, 






B 0, 10, 
SW 90° 





EW 180° 






Arc 




M 10, 10, 





A 10, 0, 





B 0, 10, 





SW 90° 




EW 180° 




ri 0.6 




ra 1 






Figure 4.3 



149 



4. Using the Program 



Amiga 3D Graphic Programming 



Sphere 

M 10, 10, 

r 10 




Cylinder 

M 10, 10, 

A 10, 0, 

B 0, 10, 

C 0, 0, 10 




Figure 4.4 



150 



Abacus 



4.1 E DIT O R D O C I M F> N TATJ O N 



C y 1 i nde r s e gme n t 



M 10, 


10, 





sw 


A 10, 


0, 





ew 90 


E 0, 


10, 








0, 1.0, 




Cone 

M 10, 10, 

A 10, 0, 

0, 10, 

0, 10, 




Spheroid 




M 10, 10, 





A 10, 0, 





B 0, 10, 





C 0, 0, 


5 




Figure 4.5 



15 1 



4. Using the Program Amiga 3D Graphic Programming 



4.1.3 The Operations Menu 



These functions make a number of operations available for working on 
object data. The most important ones can be called by pressing a key. 
With Left operations can be performed on the previous object. For 
example, when the data of the sixth object is visible, selecting the 
Left item displays the data for the fifth object. Right functions in 
the same manner, moving in the opposite direction. If no further 
objects exist, the current object is redisplayed. 

By using Segment the visible section can be chosen in the graphic 
window (see the program description of the editor for detailed 
information on this). The next three menu items (Factor, 
Factor*2 and Factor/2) change the enlargement factor. Factor 
increases or decreases the enlargement factor.Factor*2 doubles the 
enlargement factor, while Factor/2 halves the enlargement factor. 
The factor is doubled with the first, the second halves it, and the third 
can be chosen in intervals between [1/64.. 64]. The more the 
enlargement factor, the smaller the visible section, but the more 
recognizable the details. When the enlargement factor changes, the 
screen contents are unchanged because the display of large pictures takes 
too much time. A new drawing of the screen appears when you select 
the Refresh item. 

The Mat. editor item enters the material editor section of the 
program (see Section 4.1.4 below for details). You have more control 
over the speed of the graphics with the Lines item. This procedure 
can test for the number of lines used in drawing a circle, and this value 
must be between 1 and 50. The Show item displays a certain body, 
either as data or in graphic form. Graphic display can appear either in 
the middle of each window or in red. You must enter which mode and 
which body are to be used. Pressing <d> displays the data; pressing 
<c> displays the graphic body in red. When you enter <m>, the body 
section moves to the center of the window in case you want to execute 
Refresh. The Quit item lets you end the program. 



4.1.4 The Material Editor 



When you have entered the entire object list, which contains the data of 
the picture to be calculated, you have to assign each object a material 
number as well as the necessary coordinates. Each of these numbers 
represents a specific material for which you have set a certain color, 
shade intensity, and reflection factor. The material input is done in the 



is: 



Abacus 4.1 Editor Documentation 



material editor. It assigns a number to each material so that you know 
each object has the color which you assigned to it. 

All input in the material editor is done through mouse-controlled 
sliders. When you want to insert a value with these sliders, you must 
click the position inside of the corresponding slider, where the position 
on the left border means the value and the position on the right border 
means the value 1. Here we cannot insert an exact value such as 0.765. 
A value like this means nothing to the materials. Besides, you wouldn't 
be able to see a visible difference between a reflection factor of 0.7 and 
0.63. 

The color can be adjusted with the first three sliders, which stand for 
red, green, and blue. Here you can judge the color in the rectangle that 
is found in the upper right corner. You can specify the brightness of a 
body with the shade intensity. A value near zero is a dark shade and a 
value near 1 is a light shade. Which value should be inserted cannot be 
determined because personal taste is important here. When you want a 
high, hard contrast, the value must be set at 0.1. This has the 
disadvantage that objects in the shadows are barely visible. You can 
experiment with this factor as well as the reflection factor. 

Light that shines on the body should be reflected. When the body 
appears dull, the reflection factor should be increased. When it is placed 
at one, all of the light is reflected, and the body does not have its own 
color any more. When you also want to enter a material, select the 
Material item from the Mat. Editor menu, or just press the <m> 
key. After that input can begin. When all values are correctly entered, 
click on the OK gadget. You can move in the material list as usual 
using the Left and Right items. Should you want to erase a 
material, select the Delete menu item. To correct a material, select 
Correction. This reactivates the controller and the input of the 
desired material appears as usual. When all of the materials are entered, 
select Quit to return to the main program The material ediior asks if 
you really want to exit. Click on the Yes or No gadget. 



4.1.5 The Transform Menu 



There are more possibilties here to change the entered object data. The 
simplest example is editing data. Delete deletes the object data set, 
while Copy copies the data. The following commands let you choose 
the current parameters of a certain mode. This mode is tested by 
pressing a key. When you press <q>, the program exits this section 
without doing anything else. Pressing <d> executes the operation on 
the current body, and <c> copies the body, then executes the 
transformation on this copy. The transitions are: rotation, enlargement, 
and translation. 



153 



4. Using the Program Amiga 3D Graphic Programming 



The three angles of rotation must be given when the rotation is chosen. 
The midpoint remains unchanged throughout this. The new midpoint of 
the object must be entered with the translation, either through the 
keyboard or the mouse. The enlargement is just as easy. Three 
enlargement factors must be entered for the three main directions. The 
body is extended the same distance in all directions if these values stay 
the same. Otherwise the proportions of the body are distorted. 



4.1.6 The Disk Menu 



To save and reload the entered data of the object and the material list 
four items exist in the Disk menu: Load list, Save list, Load 
mat, and Save mat . When the user selects the Load list item 
from the Disk menu, the program asks for the names of the file to be 
read. The user just has to enter the filename in the string gadget and 
press the <Return> key. The program automatically adds the file- 
extension .list. 

Note : The program does not check to see if the given file is on the disk. If the 

user enters a filename that the program cannot find, the program 
displays an error message. 

After the file loads correctly, the desired data set is found in memory 
and lists the last body entered. 

When data is to be saved, select Save list from the Disk menu. 
Enter the filename without an extension, just as in loading data — the 
program automatically adds the file extension .list. 

Load mat and Save mat handle the loading and saving of the 
materials lists from and to disk. 



154 



Abacus 4.2 Tracer Documentation 



4,2 Tracer Documentation 



You can edit and shade some objects if you have put all of the modules 
together and constructed a running program. 

Editing and entering objects is made easier by the object editor. This 
section is limited to the tracer program (the main program). 



4.2.1 After Starting 



When you start the program and all the libraries open, you can specify 
the resolution and the appearance of the display screen. The display 
screen is the screen where the shaded picture and the wire model appear. 
The user screen is the screen used by AmigaBASIC. This is where all 
user input occurs. 

The first screen that appears gives you the option of selecting 
resolution. The <Cursor up> and <Cursor down> keys let you scroll 
through the choices. You can view alternatives with <Cursor left> and 
<Cursor right>. So, for example, in the first line you can establish the 
display mode (normal, hold and modify, extra halfbrite), X resolution in 
the second line (normal and HIRES), and Y resolution in the third line 
(normal and interlace). 

The last line in this screen specifies the number of bit planes. The 
program confirms that HAM and extra halfbrite run with 6 bit planes in 
the normal X resolution, and that the number of bit planes corresponds 
to the amount of memory available. 

Having established the display mode and the resolution, you can press 
<Return> and go back to the main loop of the program. Not all of the 
menu items can be used at the beginning of the program. For example, 
it makes no sense to draw a wire model when there are no objects in the 
object memory. You can access all of the menu items when the first 
object definition is loaded or merged. 



155 



4. Using the Program Amiga 3D Graphic Programming 



4.2.2 Amiga Menu 



The 3D-Cad-lnfo menu item tells you the maximum number of 
objects in memory. The objects (surfaces and bodies) are saved in array 
K(). Furthermore, array K() shows how many objects already exist. The 
program variables MaxNumber and NumberK contain these values. 



4.2.3 File Menu 

The File menu contains items for controlling printer and disk access. 

4.2.3.1 Loading and Saving Objects 



Selecting the Load item lets you load object definitions into the 
computer. The current disk directory can be displayed using requesters 
before the object file is loaded. A requester displays three gadgets: 
Files, Continue and Chdir. 

When you want to select another subdirectory from which the object 
file shouid be loaded, click on the Chdir gadget. Enter a new 
subdirectory or a new disk name. When using the optional disk for this 
book, click on the Chdir gadget. Move the cursor past the word 
tracer:. Enter the word objects and press <Return>. 

A default gadget is a gadget surrounded by a bold rectangle. Either click 
on the default gadget or press <Return> to accept this gadget. 

Click the Continue gadget or press <Return> to tell the program that 
you want to enter a filename for loading. Enter the filename without a 
file extension ( . list for object definition lists and . mat for material 
lists), and press <Return>. The program automatically appends the 
.list file extension. 

When the given file opens, the program asks how many objects should 
be loaded from this file. You can enter the number of objects currently 
in the file, a larger number or a smaller number. The default number is 
the number of objects currently in the file. In other words, this number 
is the number of elements in array K ( ) actually containing objects. 
You should provide a large enough number here in case you want to 
load more objects later. 



156 



Abacus 4.2 Tracer Documentation 



Then by selecting the Merge item you can add more objects to the 
ones that already exist. Here you should select the correct subdirectory 
as with all disk operations. 

After you open the file, you are asked how many objects should be 
loaded. Please note that if you want to load more objects than are found 
in the object memory, memory fills up and the excess objects 
disappear. 

You can avoid this by creating a large enough object memory using the 
New menu item. Objects are placed in the desired memory location. 
Memory set with New should be loaded with Merge. The object 
memory is reset when using Load. 

You can also write objects from memory to disk. Only memory that 
contains objects is written to disk. Unused object memory (array 
elements of array K ( ) ) are not saved. If the user presses <Return> 
without entering a filename, the disk operation aborts and the program 
returns to the main loop. 



4.2.3.2 Loading Materials 



You can load materials that you created with the editor into the 
computer. You can also change the current subdirectory of the diskette. 
You only need enter the name of the new material's file. These are used 
instead of the default materials that are used for shadows. Do not 
include the file extension (.mat for material lists). The program 
automatically appends the .mat file extension to the file. 



4.2.3.3 Background 



By selecting the Background item you can brighten the background 
of the graphic to be shadowed. Usually when shadowing only the 
background color or a plane is presented. But you can change this: You 
are given the option of loading an IFF graphic from the disk or creating 
a pattern. 

When you select Load Screen, a screen similar to the Load 
object screen appears. You can change directories, load an IFF 
graphic or view the files in the current directory. When you click on the 
Continue gadget the program asks for the name of the IFF file that 
contains the picture to be loaded. An IFF picture can be taken from any 
drawing program that supports Interchange File Format (IFF). Try this 
with pictures from Graphicraft® or DeluxePaint®. 



157 



4. Using the Program 



Amiga 3D Graphic Programming 



Now back to the background. When you decide on a pattern for the 
background, you can choose from three alternatives: 

Pattern Click on the Pattern gadget to fill the display screen with a fill 

pattern. Enter the first number of the desired pattern, which must be 
between and 35. This gives you a set of 36 different fill patterns 
(standard and extended). Then you need only select the foreground and 
background pen colors. The display screen fills with the pattern in the 
given color. 

Sky Let's produce a starry sky. We won't go into forming individual stars 

here because the alternatives are automatically shown from the 
program. 

After entering the star color and you enter the number of stars to be 
drawn, this background appears on the screen. 

Floating Here you can display the changes from one color to another. Simply 

background specify the number of the color register between whose colors the color 

path should be calculated. 

For example, if you want the color bright green in color register 1 and 
the color dark green in color register 3, you simply enter 1 and 3 for a 
color cycle from light green to dark green. 

Generally you should only create a background when you are sure that 
the next step will be shadowing. For example, if you are not sure if the 
position of an object is correct, you should try to determine this first. 
Loading a similar IFF file can be an easy test. 



4.2.3.4 Saving Graphics 



You can save graphics in IFF format on disk for later recall. Besides 
storing the picture, this lets you edit the picture later with a drawing 
program. Select the Save Screen item from the menu and enter the 
name of the file that should be written to disk. 



4.2.3.5 



Printing Graphics 



You can also print your graphics on paper using the tracer program. 
Hardcopy creates a hard copy on the printer selected from Preferences. 
You will also need Preferences 1.3 if you want the picture printed 
sideways or in gray scales. 



158 



Abacus 4.2 Tracer Documentation 



Select the Hardcopy item from the File menu. A requester asks 
whether a printer is connected. Click on the Printer OK gadget if so. 
Clicking the No Printer gadget returns you to the main menu. 



4.2.3.6 Setting New Colors 



Selecting the Color palette item displays all of the available 
colors on the display screen. Move the mouse pointer on the color to 
be changed and press the left mouse button to select the color. You can 
then set the new red, green, and blue components of the foreground and 
background colors. After that you can either leave the color palette 
screen or change the next color. 

Note: Selecting Color palette deletes the current graphic from the 

display screen, replacing the graphic with the palette screen. Save 
graphics often. 



4.2.3.7 Leaving the Program 



When you want to leave the program select the Program end item. 
You will be asked if you really want to leave. Click on the Yes gadget 
to leave the program. Click on the No gadget to return to the main 
loop of the program. 

By clicking on the New start gadget the entire program starts over as 
if you had just begun working. This option deletes any work that was 
in memory, so use with caution. 



4.2.4 The Editor Menu 



This item invokes the editor. Before the editor is called, confirm your 
choice. You can save a picture that was not previously saved by 
clicking on the Cancel gadget and saving the graphic. 



159 



4. Using the Program Amiga 3D Graphic Programming 



4.2.5 The Parameter Menu 



This menu contains routines which change the parameters for the three 
dimensional display. 

You can reset the coordinates of the projection point with the 
Projection point item. The Main point item lets you 
control the coordinates of the main point. The rotation angle around the 
coordinate axes can be changed in a,$,%. The distance from the 
projection to the main point can be reset from the Distance item. 

As you know, the body of an object appears as a wire model. This is an 
alternative to the very slow shadow process. When you enlarge the wire 
model, the object also appears larger when it is shadowed. You have 
two options of enlargement: 

Proportional Here you enter an enlargement factor. The picture is then enlarged in 
the X and Y directions by the same measurements. 

Distorted A section of the screen must be selected with the mouse for a distorted 

enlargement. Press the left mouse button so the pointer position 
determines the upper left corner of the rectangle. Move the mouse while 
holding down the button and you can see how the mouse movement 
reduces and enlarges the rubberbanded rectangle. 

When you have set the correct rectangle, release the left mouse button. 
You are then asked whether the chosen section is OK. Click on the OK 
gadget if it is. If you would prefer to enlarge another section, click 
anywhere outside of the OK gadget. 

When the section is OK, the contents of the specified rectangle are 
enlarged. 

The default proportional enlargement factor is one, which returns you 
to the original screen. In some cases you may see anything on the 
display screen after the enlargement. This can be remedied by choosing 
Enlarge again and this time entering a proportional factor of 1 to 
restore the original picture. Then select the Enlarge item and click 
on the Distort gadget to enlarge the appropriate section. 

Number of lines should also be explained. Remember: the 
number here (numbersegments) gives the number of lines used to 
draw a circle in the wire model. Only numbers are given in the above 
menu items and no requesters are used. 



160 



Abacus 4.2 Tracer Documentation 



4.2.6 The Draw Menu 



This menu lists items for controlling the shadowing as well as drawing 
wire models. 



4.2.6.1 Shadows 



Select the Shadows item to start the shadowing process. 

You must first determine the parameters used by the shadowing process 
first (Shadow window, etc.). 

This is done by choosing Initialization. First you are asked 
about the actual shadow window. Click on the All gadget to shade the 
entire screen. Section gives you the option of choosing a particular 
screen section. 

YA-YE gives you the option of specifying a vertical area (a stripe) to 
shade. This stripe covers the whole width of the screen; you can set its 
position and height. First move the mouse to the beginning position of 
the stripe to be shaded. A line drawn at the current mouse position 
helps with the positioning. When you have found the correct position, 
press and hold the left mouse button while moving the pointer to the 
desired end position. Release the mouse button to select the stripe. 

You can decide the end first and then the start positions of the stripe. 
The sequence is the same. The program ensures that the sizes of the Y 
coordinate of the end and the smaller Y coordinate of the start position 
are correct 

We now come to more parameters for the shading. You must enter the 
coordinates of the light source. Simply enter the X, Y, and Z 
coordinates of the light source in Qx, Qy, and Qz. Be aware that the 
light source rotates around the coordinate axes. 

You can also set the color of the light source. Enter the red, blue, and 
green components of the light source in values between and 1 . Three 
ones give a white light source. 

For values between and 1, be sure that you include a zero preceding 
the decimal point. For example, the program accepts the notation 0.5 
in these cases, but will ignore an input of .5 — remember the zero 
before the decimal point. 



161 



4. Using the Program Amiga 3D Graphic Programming 



Because the shading can take many days or weeks on complicated 
pictures, the pixel sizes can be changed. This has the advantage that 
you can calculate a large picture within a few hours. All of the points 
of the shade window can be shaded by setting the pixel width and pixel 
height at 1. When an unpleasant result occurs, this can be changed by 
resetting some of the parameters. 

Choosing a pixel width and pixel height larger than 1 makes every 
second, third, fourth, etc., point available for color calculation. The 
picture is also shaded in a point width * point height grid. 
The midpoint of such a grid rectangle is the color of the entire 
rectangle. 

After all of these parameters are entered, you can then choose the 
Shadows menu item to start the shadow calculation process. 

You can control the default values for shading by changing the values 
in the program. The picture on the cover of this book was produced by 
shading the entire screen with the light source is set at the coordinate 
(0,0,50) with the color (1,1,1,) = white. Pixel width and Pixel 
height are both 1. The projection point was 270,10,255 and the 
main point was 0,0,25. The object and material were loaded from the 
optional disk from the Spheres . list and Spheres .mat files. 
The enlargement factor was 4. 

You shouldn't try to use the keyboard during shading. When you press 
any key during the shading operation, after the current line is shaded, 
the program asks if the shading should be continued or stopped. 

You can, for example, let the computer shade overnight and save the 
picture in the morning. Naturally you could object that the Amiga is a 
multitasking machine. Therefore AmigaBASIC could be started from 
the CLI to allow other work in the AmigaDOS window. This is not 
recommended since too many interruptions of the shading task can 
cause a Guru Meditation. 



4.2.6.2 The Wire Model 



When you select the Wire Model item, the wire model of the object 
is redrawn on the display screen, or if it has already been drawn, the 
display screen is redisplayed. 

This happens if no parameters (projection point, main point, distance 
to projection surface, rotation angle) have changed since the last 
selection of the wire model item. When one of these parameters is 
changed, or the display screen is erased using the Clear screen 
item, or a background is chosen, the picture is redrawn. 



162 



Abacus 4.2 Tracer Documentation 



After choosing a background for the display screen the new drawing is 
not erased. The wire model is drawn over the background. When the 
wire model finishes drawing, the screen flashes briefly. The wire model 
stays on the screen until you press a key. Then the program returns to 
the main loop. 



4.2.7 Keyboard Program Control 



We included keyboard shortcuts for some menu items to make the 
program easier to use. For example, pressing <Space> creates a wire 
model. 

The menu items that can be addressed from the keyboard show the key 
to the right of the item name. There are also functions that can be 
called using the keyboard instead of the menu. 

One of these is Help. By pressing the <Help> key a list of keyboard 
codes and their actions appears on the screen. 

You know, for example, that the rotation angle can be increased and 
decreased using the cursor keys, the <R> key and <CtrlxR>. The 
distance to the projection surface (DPH) can be changed using + - * /. 

That's it for keyboard and menu control of the program. Going deeper 
into this subject is unnecessary, because you can only be a tracer expert 
through practice. 



163 



5. 

Program 

Enhancements 



Abacus 



5. Program Enhancements 



5. 



Program Enhancements 



Extended 
objects 



The algorithms and routines in this book are not as complete as they 
could be. Improvements of all kinds could be made here and there 
throughout the program. We'll look in this chapter at some of the 
improvements that can be made to the programs you've read about so 
far. Perhaps youVe already thought of your own enhancements to the 
tracer and editor programs, or perhaps this chapter will help you think 
of some improvements. 

Let's start with the basic objects. We can give the objects more 
restrictions than already exist in the tracer and editor. For example, with 
a little reprogramming we could add cone segments, truncated cones, 
ellipsoid segments, etc., to our list of basic objects. Because these 
restrictions are not that different from the complete objects, they can be 
created from the existing subroutines and added to the editor's menu set 
as needed. 



Triangles and 

extended 

objects 



B-splines 



Smooth 
shading 



It's even possible to create new basic objects which have little basis in 
the original object routines. For example, imagine what might happen 
if you change the restrictions of an ellipsoid to u A 10+v A 10+w A 10=l. 
What would you get? A cube with rounded corners? Change the 
restrictions of the other basic objects, perhaps by calculating a cube 
instead of a square, or something similar. 

Another option for creating new forms consists of assembling multiple 
triangles. You can make almost any figure if you have enough triangles 
available for creating it. Unfortunately, it's rather time consuming to 
enter each individual triangle. 

Try both methods of creating a surface that has separate passages, but 
no corners or edges. This is done with B-splines that run through the 
points of the surface. The problem with this is that a surface must be 
divided into many triangles so that they function very smoothly. 

The big advantage to B-splines lies in that you can get wonderful 
shapes with little programming hassle. You can define a wine glass for 
the computer to calculate with a few dozen points. By using Bezier or 
B-splines a few thousand triangles are created which then create a nearly 
perfect illusion. 

In addition to Bezier or B-spline, you can use smooth shading. Smooth 
shading erases the edges from surfaces by calculating the normal vectors 
of the two surfaces in such a way that they are continually changing. 
You must define which surface is being pushed against for each edge of 
the surface you are working with. 



167 



5. Program Enhancements Amiga 3D Graphic Programming 



The calculation of these surfaces is fairly easy. You must find the 
normal vectors of the other surfaces and join them together 
independently of the distance of the intersection point from the shifted 
edge. When the intersection point is very far from the shifted edge, take 
the original normal vector, which is directly on the intersection point, 
and add the normal vectors of both surfaces in the ratio of 50 to 50. 

You don't need to work out as many triangles with smooth shading 
because the borders are smooth. The program coding involved requires 
more memory, and the computation time increases as well. The 
disadvantage of smooth shading is that only the normal vectors are 
smoothed. The outline of the surface remains unchanged. If you change 
the surface of a cube into that of a circle, the border will keep the 
appearance of a cube. 

Object Object rotations present another simplification of the input of objects. 

rotation These can be done with cylinders, cones, and circle surfaces. You must 

write an editor that lets you enter the profile of a rotation body. From 

that profile the data of the object can be generated and saved to disk. 

You can create a section from a rotation body, but the cone section 

must also be implemented. 

As you see, the basic objects have room for improvement. You can 
have more options for creating shapes by changing the surface structure 
of the objects. 

Until now all of the objects have been the same in that they were 
smooth. We can define different material constants which affect only 
the color and reflection coefficient of the surface. Wouldn't it be nice if 
we could define any relief for a surface? Calculation solves this 
problem. In relationship to a function, which tests for the method of 
the relief, the normal vectors are bent. This happens in relationship to 
the position and is repeated periodically, and produces a very ordinary 
relief. A small disadvantage of the relief is that it is only related to the 
normal vectors; the surface itself remains smooth. You should always 
use small reliefs because they do not draw attention to themselves. 

We define the relief function in relation to both parameters of the 
direction vectors u and v for planes. For spheres and ellipsoids we take 
the angle of the polar coordinates of the intersection point, and for 
cones we take the polar coordinate angle, which is responsible for the 
rotation around the r4 axis, and the w parameter for the r4 axis. We 
leave writing the relief function up to you and your imagination. 

A pattern affects more changes in the surface. It's up to you to decide 
whether the pattern will be a chessboard pattern, stripes or small hearts. 

Patterns do not change the normal vectors of a surface, but change 
colors or the entire material constant. The pattern should be defined 
periodically, in relation to the parameters or the polar coordinates. It is 
best if the pattern is defined in the Mat array. For example, take 



168 



Abacus 5. Program Enhancements 



Mat (n, 6) , which is unoccupied. When this element is zero, this is 
valuable for the other elements we have defined. Otherwise Mat ( n , 6 ) 
gives the number of the pattern. For example: 

1: Chessboard 

2: Dotted 

3: Lined 

4: ... 

Mat (n, 0) through Mat (n, 5) contain the material numbers for the 
different materials of the pattern. We can assign different materials for 
the black fields and the white fields of the chessboard pattern. The 
hearts could be multicolored, or you could define a red-and-blue 
Commodore symbol. We can define the pattern using parameters and 
polar coordinates like the relief. We could also use different methods, 
for example in relation to the Z coordinate so that you get high lines. 

IFF So far we've learned how to project a graphic on a surface and how to 

improve the data structure. Now we must build the ability to load an 
IFF graphic into the program. We must specify where the graphic 
should be on the surface and if it should lie next to it, like our pattern. 

Instead of the color that is defined in the Mat array for the surface, we 
take the color that is used in the graphic. The X and Y coordinates of 
the graphic are calculated in the approved method from the 
parameters/polar coordinates. The other material attributes, like 
reflection, etc., can stay the same. Put a bottle, which was defined with 
Bezier, smoothed with smooth shading, and distorted with some good 
taste, into a BASIC program. We are operating our Amiga to the limits 
of its capabilities, both in computing time and in resolution and color. 

Transparency Now we want to turn to other things to make our graphic more 
realistic, such as transparency. We have already described how to 
simulate transparency. It's not enough to construct a 
CalculatePoint call in the respective subroutine. We must also 
consider that a transparent object allows light to pass through, so there 
is light beneath the object instead of a shadow, but light whose color is 
not quite the same as the original color. 

We can build transparency for the place we have already prepared in our 
material data structure. We have constructed another call for this routine 
in CalculatePoint, before the recursive call from 
CalculatePoint for the reflection. The direction vector of the 
visual ray (rx,ry,rz) is unchanged. We must be careful that all 
variables that are needed for the CalculatePoint call are not 
changed. The object is searched first, the shadows thrown from the 
point in question, and the light source is next. Then the color of the 
light rays change according to the material structure of the object. After 



169 



5. Program Enhancements Amiga 3D Graphic Programming 



that the object must be searched, then the light source, and so on, until 
all of the objects that throw shadows on the point in question are 
known. The calculation of Bright . r, Bright . g, and Bright . b 
for the color must be considered. The consideration of the color of the 
light source must then be preferred and may not be executed twice in 
the case of shadows. 

Calculating transparency is not quite as easy as reflection, and both 
things together make it even more complicated. For the definition of 
the materials the sum of the reflection and transparency coefficients 
should not exceed one because the brightness of the surface can 
eventually be greater than one, which would produce a realistic 
impression. 

As a last feature we make it possible to define multiple light sources. 
We must execute all calculations for each light source and the colons we 
get. The addition of the brightnesses of all of the light sources should 
not give a value over one, because our graphic could get too bright. To 
be able to use the optimization, a MinMaxLq array must be calculated 
for each light source, or we enlarge the MinMaxLq array around one 
dimension which gives the number of the light source: 

DIM MinMaxLq (NuniberLq,Nuniberlk, 6) 

Maybe you like more optimizations, if only for more light sources. Or 
you have an idea for more shapes. This chapter only shows a starting 
point, which should give you an idea of the possibilities that are 
possible in ray tracing. These possibilities are left up to you to use and 
find. Computer graphics are a fascinating subject; make the best of it. 



170 



6. 
3D Tricks and Tips 



Abacus 6. 3D Tricks and Tips 



6 . 3D Tricks and Tips 



Now that you have read through most of this book, we'd like to give 
you some practical hints. These tricks and tips will help you design 
graphics for your current 3D system more easily, and help eliminate 
most errors. 

Graphic First the design. One of the most difficult problems is thinking about 

planning the scenery that the computer should calculate. At first, try it with just 

a few simple objects. Too many objects clutter the picture and confuse 
the viewer. Don't go into too much detail — limit yourself to the 
important items. This book lists some examples. Or load some objects 
from the optional disk if you don't want to type them in yourself. 

When you have some idea of the body you want drawn, sit down and 
sketch it out on graph paper. Graph paper allows for easier 
measurement. Draw three views of your object, the way the editor will 
draw the object. You should also lay out the material constants for each 
object material and include these in the working sketch, where each 
material is assigned a number. 

Handy tools One of the best items you can have available for keeping track of your 
3D parameters is a small notebook and pencil. Keep these next to the 
computer when using the tracer program. Write down original 
coordinates of graphics, experimental coordinates, colors, etc. (you may 
also want to write down whether these experiments worked or not). 

Colors When choosing color, try to keep the graphic from appearing too bold 

or too dull. Select colors that complement each other well, instead of 
using every color available. Assign these colors to individual objects 
where they will look best. 

Shading and The shade brightness should be set at roughly the same value for all 

reflection objects (0 to 0.25). The reflection value can be somewhat higher. Add 

reflective properties to single objects, instead of the entire scene. Have 

the appearances of the objects set in your mind to help add these 

properties to the actual graphic. 

When the mental picture meets your satisfaction, start the editor and 
enter the individual objects. Later, when you have given more thought 
to the scene, you can divide it up into sections and enter the data 
directly into the editor. 



173 



6. 3D Tricks and Tips Amiga 3D Graphic Programming 



Keeping it To keep your graphic from becoming too complicated, you should set 

simple visible to y (yes) for all objects in the editor, so you can see 

exactly what you have entered. After entering each object and editing it 
to your satisfaction, save the object. Load the materials editor and add 
the material constants. Save the entire collection of data, then start the 
tracer. 

Resolution Now you must decide in which resolution you want the picture 

calculated. The HAM mode offers the most colors, but a HAM screen 
consumes quite a bit of memory. When you have enough memory, you 
can choose a HAM screen at the start because the color palette doesn't 
need to be selected so carefully. 

Point of view After you have loaded your objects and materials, you must consider at 
which angle the scene should be observed. Examine your sketch and 
consider the point of view from which you want to the scene to appear. 
Experiment with changing the main point first (the default when 
loading objects for the first time is usually 0,0,0). Try some negative 
and positive settings. 

Next experiment with your distance between the projection point and 
the main point (DPH — see Section 2.4). Be careful not to make this 
figure too small, since this can greatly distort perspective of the 
graphic. 

Projection Now enter your projection point. Enter the coordinates (-1000,- 

point 1000,1000) if you have no other position specifically in mind. Press 

<Space> to see the wire model. It is probably relatively small on the 
screen. Press <v> to enlarge the picture and select either the 
Proportional or Distort gadget. The object should almost fill the 
screen, without going past the edges. When you define reflecting 
objects, select a larger section so the reflections appear on the screen. 

Experiment with each point until the display pleases you. Write down 
all of the values that you have entered, including the main point, 
enlargement factor, and either the projection point or angle and distance. 
This will help if you want to reproduce these conditions later. 

Light source Now specify the position of the light source. A recommended value is a 
position "to one side" of the observer, so the shadows are most distinct. 
Try the projection point at (-1000,-1000,1000), and the light source at 
(-1000,1000,1000) if you want the shadows to fall to the right. If you 
want short shadows, increase the Z coordinate of the light source's 
position. Decrease the Z value for longer shadows. 

Write down the position of the light source in the notebook. Press 
<F9> to initialize shadowing parameters. Select the entire screen or a 
section, and enter the position of the light source. Enter (1,1,1) for the 
light source color, which provides a white light. 



174 



Abacus 6. 3D Tricks and Tips 



Big pixels for For the pixel height and width, enter 16 and 10 (1/20 of the screen 
draft height and width). This computes the shadowing in a blurred form. 

calculation These pudgy pixels are enough for a draft display, since calculation 

time is 1/400 the time normally needed. 

Press <F10> to calculate the picture. Clock the time between the 
setting of the first and last pixels. After the picture is complete, you 
can approximate the amount of time the computer needs to calculate the 
picture with normal single pixels. Use the following equation: 

calculation_time * pixel_width * pixel_height 

The result of this multiplication gives you a rough idea of the 
calculation time. 

If you're nearsighted, take your glasses off and back away from the 
screen until the draft graphic looks close to a normal close-up view 
(people with normal vision can just back away). This gives you an idea 
of what the finished product will look like. 

Colors Now you can see if the colors came out as you had thought. It is very 

important that you ; et the color palette at the optimal setting, even for 
HAM pictures. Set the color palette so that many different shades of 
brightness are available for each color. The more colors you have to 
use, the more degrees of brightness you can set. 

Set the color palette for HAM mode so each sudden transition from one 
color to another requires no more than two colors in the palette. 
Transitions from black to red, black to green, or black to blue are no 
problem, while a transition from black to gray cannot be done directly 
because this gray tone is not in the palette. 

Once you have set the colors properly, the picture can be calculated. If 
you select a smaller pixel size (e.g., height and width of 2), you can 
recognize more features. When you are satisfied with the result, you can 
consider whether you want to stay with this display mode, or change 
modes. If you want to change, you should write down the color palette 
configuration for later reference. 

Before you calculate the picture in normal pixel size, you should figure 
out how long the computer will take to compute the graphic (see 
calculation described above). It's not a bad idea to plan to let the Amiga 
calculate overnight. 

Calculating in If the computer needs days to compute, which happens in more 
sections elaborate graphics, you can calculate the picture in sections and save the 

screen. You can then calculate further by loading the graphic, setting 
the necessary parameters and selecting the sections not yet shadowed. 



175 



7. 

Mathematical 

Basics 



Abacus 



7. Mathematical Basics 



7. 



Mathematical Basics 



Some people suffer from math anxiety. This book was designed for the 
non-math person in mind, but we should list a few of the equations 
involved. We would like to show you some of the basics of three 
dimensional math in this chapter. 

Before we go any further, let's remind you of a word you've seen 
repeated throughout this book. We first defined it in Chapter One, but 
k can't hurt to describe it again: 

Algorithms An algorithm is a step-by-step plan for problem solving, usually 

through computer programming. Often a computer book explains the 
algorithm needed for the particular task, then lists the program used to 
perform that task. We chose to do it the other way around. This book 
views algorithms as working programs instead of as formal "statements 
of intent." Therefore, we showed a segment of a program listing first , 
then we discussed the algorithms used by the program. In short, you 
saw the program code itself, then the reasoning behind the way the 
program code works. The programs were written as modules so you 
could incorporate the routines in your own programs. The completed 
program listings for the tracer and editor are listed in the appendices. 



7.1 



Vectors 



Figure 7.1 



First we should look at vectors. A vector acts as a connection between 
geometry and standard arithmetic. Vectors are graphically represented as 
arrows. Each vector arrow has a starting point and an end point; the 
fflTow's "head" lies at the end point. Vectors with the same length and 
direction are equal, regardless of tfceir location. The following illustra- 
tion shows a set of equal vectors and a set of different vectors: 



Equal vectors 



Different vectors 





In geometry there are two ways to differentiate vectors: 



179 



7. Mathematical Basics 



Amiga 3D Graphic Programming 



1 . position or equal vectors and 

2 . direction or difference vectors 

Position vectors begin at the origin of the coordinate system (0,0,0). 
Position vectors require that you only give the end point-the beginning 
point is already set at 0,0,0. Parts of the space can also be assigned as 
position vectors. 

Direction or difference vectors start at locations other than the origin 
and are usually the difference between two position vectors. The start- 
ing point of a direction vector is usually the end point of a position 
vector. 



Figure 7.2 




osition vector 



Direction 
vector 



The difference vectors bring up an important subject: Computing with 
vectors. You can add and subtract vectors: 




Figure 7.3 



180 



Abacus 



7.1 Vectors 



+ 




Figure 7.4 



You can add or subtract the vector components (vectors have X,Y,Z 
components', points have X,Y,Z coordinates): 

(ax) (ox) (ax±ox) 

a±6 = (ay) ± (oy) = (ay±oy) = 
(az) (oz) (azioz) 

When multiplying a vector with a scalar (a real number), multiply each 
component by this number: 

ax (t*ax) 
t*a = t*ay = (t*ay) = u 
az (t*az) 



ax (t*ax) 

t * ay - (t*ay) - 

az (t*az) 



l*a 



k*£ 



Figure 7.5 



181 



7. Mathematical Basics 



Amiga 3D Graphic Programming 



7.2 



Using Vectors 



You can describe all sorts of three dimensional bodies and surfaces with 
vectors; these are the connection between math and geometry — and 
computer graphics. 

Lines are also represented by using vectors. You take a position vector 
that fixes a point on a line, and a direction vector that lies on a position 
vector. The following equation can describe a line: 



X 


ox 


rx 


y 


oy + 1 * 


ry 


z 


oz 


rz 



The above equation looks like the following in graphic form: 



Figure 7.6 



Direction vector 




Planes 



The direction vector extends like a telescope arm to the length stated in 
1 and encompasses all of the points of the line. 

Planes are presented in a similar way. Two linearly independent vectors 
are needed here. Linearly independent means that one vector is not a 
factor of the other. The plane equation looks like this: 



x ox rlx r2x 

y = oy + a*rly + b* r2y 
z oz rlz r2z 



Spheres 



The equation used to prepare spheres may be a little more intimidating. 
The equation itself appears below: 



(x Mx)"2 

(y - My) "2 

(z Mz)"2 



This diagram makes it somewhat clearer 



182 



Abacus 



7.2 Using Vectors 



Figure 7.7 




In the sphere equation notice that a point on the surface of the sphere is 
created from other vectors, instead of being based directly on the point 
of origin of the sphere. And the vector squaring is new. The difference 
of these two vectors (point on the sphere-midpoint) is the radius, in 
which case the point lies on the surface of the sphere. 

Why is it squared? Because squaring must occur when a vector is 
equated with a scalar. By squaring, the scalar product becomes a real 
number: 

y*2 = x*x+y*y+z*z = a 
z"2 

When this number is equal to the square of the radius, you know: 



The point (position vector) y lies on the sphere 

z 

This is also true for the basic objects and surfaces that can be created 
with vectors. 



183 



7. Mathematical Basics 



Amiga 3D Graphic Programming 



7.3 



Angles Between Two Vectors 



Figure 7.8 



You can also test for the angle enclosed by two vectors. Let's move 
outside of the space in the plane and look at two perpendicular vectors: 




One of the vectors (6) can be extended by S-multiplication until it is 
exactly as long as the other vector (a). Examine the coordinates or 
components of the vectors, then note that the following apply: 

ax = -o'y ay = o'x 

Because 6' is a factor of vector 6, you can write k* 6 for 6': 

ax = -k*oy ay = k*ox 

By solving k and inserting and transforming the equation, you get: 

ax*ox+ay*oy = 

This is also a form of the scalar product placed between two vectors. 
Consider two non-perpendicular vectors: 



184 



Abacus 



7.3 Angles Between Two Vectors 



Figure 7.9 




Now look at the equation for this (note: the a character represents the 
Greek letter alpha; the P character represents the Greek letter beta): 

ax = Cos (a) * |a| ox = Cos (P) * |6| 
ay = Sin (a) * |a| oy = Sin(P) * |6| 

If you place these in the equation of the scalar product: 

Cos (a) * | a| * Cos (p) * | 6 | 
- Sin (a) * |a| * Sin(P) * |6| = ax*ox +ay*oy 

< = > (Cos (a) *Cos (P) - Sin(a) *Sin (P) ) * |a| * |o| = 
ax*ox+ay*oy 

The expression with the many sine and cosine functions can be simpli- 
fied by using the addition theorem of cosines : 

(Cos (P-Ot) = Cos (a) *Cos (P) +Sin (a) *Sin (P) ) 

ax*ox+ay*oy 
Cos(P-Ct) = 

lal * |6| 

Where the angle P-a is enclosed by the vectors. 

For the value of a vector (lal) use the Pythagorean theorem: 

|a| = Sqr (dax 2 +day 2 +daz 2 ) 



185 



7. Mathematical Basics 



Amiga 3D Graphic Programming 



y2-yl = dy 



Figure 7.10 




x2-xl = dx 

dax represents the difference of the X-end-component minus the X- 
starting-component of a vector, day and daz stand for the difference 
between the Y and Z components, respectively. 

Insert the value of the vector in the formula for the cosine and examine 
the two vectors in the space, and you get two vectors for the formula of 
the cosine of the enclosed angle: 



Cos (p-CX) 



ax*ox+ay*oy+az*oz 
Sqr ( (dax 2 +day 2 +daz 2 ) * (dox 2 +doy 2 +doz 2 ) ) 



186 



Abacus 7.4 Intersecting Lines and Planes 



7 . 4 Intersecting Lines and Planes 

Now we'll examine the intersection points of lines and planes, and 
lines and spheres. These intersection points are especially important in 
shading three dimensional bodies. You must test for the point of a 
surface on which a visual ray (light), represented by a line, falls. 

We use a line equation for the visual ray, as well as a body equation for 
the body. 

For the sphere you need to insert the line equation for the point on the 
surface of the sphere and view the individual components to understand 
the intersection point: 



(ox 


9 

rx Mx) £ - 


(oy + 


l*ry +My) 2 


(oz 


rz Mz) 2 



Take the x component, for example: 

(l*rx + (ox+Mx) ) 2 = r 2 

The 1, for which the line and the sphere have an intersection point, can 
be tested with the help of the binomial formula and by solving the 
quadratic equation. The 1 is the telescope factor with which the 
direction vector of the line must be multiplied to meet on the sphere 
surface. When the quadratic equation is unsolvable, no intersection 
point exists. 

Intersection point factors look more complicated still when considering 
a line and a plane. Here the line and the plane equations must be set to 
equality: 



ox rx 


ax rlx r2x 


6y + l*ry 


= ay + a*rly + b*r2y 


oz r z 


az rlz r2z 



Then you must create the equation for each component and ensure that 
all variable elements are on the left side of the equation, and constants 
are on the right side: 



l*rx - a*rlx - b*r2x = ax-6x 
l*ry - a*rly - b*r2y = ay-6y 
l*rz - a*rlz - b*r2z = az-6z 



187 



7. Mathematical Basics Amiga 3D Graphic Programming 



Now we have an equation system with three variables (1, a and b) and 
three equations. This 3x3 equation system can be solved using a deter- 
minant. 

You must build a matrix from the equations. Take all of the coeffi- 
cients of the variables and write these in a matrix: 

rx -rlx -r2x | ax-6x 
ry -rly -r2y | ay-6y 
rz -rlz -r2z | az-6z 

The coefficients for the same variable must be beneath each other. The 
matrix also has the following form, where a stands for the coefficients 
and b stands for the constants: 

all al2 al3 | bl 
a21 a22 a23 I b2 
a31 a32 a33 | b3 

You can now begin constructing the determinant: 

D = det A = | all al2 al3 I 
I a21 a22 a23| 
I a31 a32 a33 | 

all a22 a33 + al2 a23 a31 + al3 a21 a32 
- al3 a22 a31 - all a23 a32 - a33 al2 a21 

Besides this denominator determinant you must create three more 
number determinants: 

|bl al2 al3| 

Dl = det Al = |b2 a22 a23| 

|b3 a32 a33 I 

bl a22 a33 + al2 a23 b3 + al3 b2 a32 
- al3 a22 b3 - a23 a32 bl - a33 al2 b2 

I all bl al3 | 

D2 = det A2 = |a21 b2 a23| 

|a31 b3 a33 | 

all b2 a33 + bl a23 a31 + al3 a21 b3 

- al3 b2 a31 - a23 b3 all - a33 bl a21 

I all al2 bl | 

D3 = det Al = |a21 a22 b2 | 

Ia31 a32 b3 | 

all a22 b3 + al2 b2 a31 + bl a21 a32 

- bl a22 a31 - b2 a32 all - b3 al2 a21 



188 



Abacus 7.4 Intersecting Lines and Planes 



Why these determinants are called numerator determinants and 
denominator determinants is something we'll discuss now. To solve the 
equation system you must get the quotient from a numerator and 
denominator determinant. 

This depends on the positions of the variables in the equation system, 
which are used by the numerator determinant. In our example 1 stands 
in the first place. The quotient Dl/D is made for this variable to test for 
the 1 of D. 

The solution for a and b follows in the same way: 

a=D2/D 
b=D3/D 

That functions only when the denominator determinant isn't equal to 
zero because division by zero is undefined. When D=0 the equation 
system has no solution, or, in other words: the plane and line have no 
point in common. 

We have addressed some basics of three dimensional math, and hope 
you have been able to understand them. 



189 



8. 
The Optional Disk 



Abacus 8. The Optional Disk 



8. The Optional Disk 



The tracer program modules contained in this book are found on the 
optional disk in the modules subdirectory. The screens directory 
contains some ILBM format files generated with the tracer program that 
show the fantastic capabilities of this program. 

You can see the sample graphics by booting the optional disk. Turn off 
your Amiga and eject any disks in the drives. Turn on your Amiga. 
When the Workbench disk hand icon appears, place the optional disk in 
drive dfO:. A graphic appears on the screen. To end a graphic display 
click on the upper left corner of the screen. The next graphic then 
appears. Click the upper left corner to end the display and get to the 
CLi prompt (1>). 

The C language routine that reads and displays IFF screens 
(ShowiLBM in directory c) reads any IFF graphic once compiled. The 
routine's source listing appears in the modules directory. 

We couldn't include more than two demonstration graphics on the disk 
due to memory restrictions. An executable tracer/editor disk requires the 
following files and directories: 

editor program (either editor . bas or editor . run) 

libs directory (contains the necessary . bmap files) 

complete tracer program (either your merged BASIC tracer or 

tracer, run) 

SetPoint . B program (see Appendix D) 

AmigaB ASIC (if you're running uncompiled programs) 

objects directory (see description below) 

Now we come to the last directory on the disk. Many object definitions 
are found in the objects directory. The results of three of these 
objects are found in the screens directory. The picture on the cover 
of this book was generated using the tracer program and the 
Spheres . list and Spheres .mat files. The point of projection 
was 270,10,25, the main point was 0,0,10 and the enlargement value 
was 4. Shadow initilization was ALL, light source was 0,0,50, light 
colour was 1,1,1 amd pixel width and height was 1,1. The picture took 
about two weeks to generate completely on the uncompiled tracer. 

The optional disk also contains compiled versions of the editor and 
tracer programs, named editor, run and tracer, run. They were 



193 



8. The Optional Disk Amiga 3D Graphic Programming 



compiled using AC/BASIC VI. 3. The programs required a few 
modifications to compile successfully. The next section explains these 
modifications in detail. We strongly recommend compiling these 
programs, since they run about 50 times faster than the original BASIC 
versions. For example, a graphic that the original BASIC version of 
the tracer needed three weeks to compute was finished in about six 
hours using the compiled tracer program. 



8 • 1 Compiling the Programs 



The fun of ray tracing wears thin very quickly once you find how much 
time the calculations require. The computations become even slower 
when the ray tracing program is written in a slow language. We decided 
to compile our programs to get the most speed out of them. 

Please remember that the optional disk for this book already contains 
compiled versions of the editor and tracer. Do not try to compile these 
two pre-compiled programs. However, it may be worthwhile for you to 
try compiling the uncompiled versions of the programs after you read 
through this chapter. 

Naturally you can use any compiler which is compatible with 
AmigaBASIC. At the time this book went to press, we only had one 
compiler available — the AC/BASIC Compiler from Absoft. The 
following description applies to Version 1.3 of this compiler, released 
April 10, 1988. 

The first item of business is to make a backup copy of your disk. 
You'll use this backup disk for compiling: Remove any unnecessary 
files from the disk — keep only the uncompiled sources for the ray tracer 
and editor (do not copy the compiled versions of the tracer and editor). 

No te : Never use an original disk for compiling. Always use a copy! 



8.1.1 Compiling the Editor 



First let's compile the editor. This is easy — load AmigaBASIC and 
enter the following in the BASIC window: 

CLEAR ,140000 
LOAD "Editor .bas" 



194 



Abacus 8.1 Compiling the Programs 



Once the editor finishes loading, save it as an ASCII file using the 
following: 

SAVE "Editor .cmp", a 

The " , a suffix saves the program in ASCII format. The compiler can 
only handle ASCII files — it can't compile straight AmigaBASIC 
programs. The . cmp extension saves the ASCII file without 
overwriting the original BASIC program. Quit AmigaBASIC. 

Now load the editor source text into an editor (e.g., ED). You must do 
some adapting of commands, since the compiler cannot handle a few of 
the commands which appear in the source text. You could have made 
these changes using the AmigaBASIC editor, but since it has no search 
and replace facility, it will take longer. We recommend that you use a 
text editor or word processor. 

Search for the chain command. You'll find it in the Ende 
subroutine. Replace this command with END. The reason for doing this 
is that the compiled version will not recall the tracer properly. If you 
have a later version of the AC/BASIC Compiler (or another brand of 
compiler) which correctly accesses the CHAIN command, replace the 
CHAIN command with: 

CHAIN "Tracer. run" 

That's almost all you have to do to the source. Now for exiting the 
program. The compiler will not accept the quit variable. You could 
press <CtrlxC> to exit, but that isn't very elegant. Look at the menu 
reading routine toward the beginning of the program for our key line: 

IF chose=ll THEN 

CALL finish(quit) 
END IF 

Replace the CALL finish (quit ) with the following: 

GOTO Ende 

Save the editor code and exit your text editor. Copy your editor source 
code to the RAM disk. 

Make a backup copy of your AC/BASIC compiler disk. Discard all the 
unnecessary files from this backup to make room (e.g., drawers named 
Chapter, bspread and examples). All you should be able to see 
in this backup disk's window are the files a c -basic and sort subs. 
Copy your editor source text from the RAM disk to the backup 
compiler disk. 

If your sortsubs program is still straight BASIC code, compile it 
before you do anything else. Double-click the sortsubs icon. When 
sortsubs requests the filename, enter editor . cmp and press the 



195 



8. The Optional Disk Amiga 3D Graphic Programming 



<Return> key. When sortsubs requests the location of temporary 
files, press the <Return> key (Yes). This program moves all the SUB 
programs to the end of the source text. 

Once sortsubs ends, double-click the compiler icon. Select the 
following compiler options: 

N: This ensures that the editor uses ON menu GOSUB and ON MOUSE 

GOSUB 

R : Link in the runtime library (the compiled editor won't do anything 

without looking for this first) 

T: Keep temporary files on the RAM disk, which speeds up compilation 

(you can do this only if you have enough RAM — at least 1 megabyte) 

Be sure enough memory exists on the disk (the editor requires 120K). 
Delete some graphics from the screens directory. The compiler 
overwrites any existing compiled versions of the program, so make 
sure you didn't have a copy of the original compiled version on the disk 
you're using for compiling. Start the compiler and wait a few minutes. 
If no errors occur, you're over the first hurdle. Rename the finished 
editor editor . run. 

If you try out the compiled editor, you'll discover a big difference in 
speed from the uncompiled AmigaBASIC version. 



8.1.2 Compiling the Tracer 



We'll now walk you through the steps of compiling the tracer using the 
AC/BASIC Compiler. First make a backup of the disk containing the 
tracer modules (you may want to add AmigaBASIC to this disk 
temporarily). Name this backup disk tracer using the Workbench 
menu's Rename item. 

Load AmigaBASIC. Enter the following in the BASIC window and 
press <Return> at the end of each line: 

clear, 140000 
chdir "modules" 

Enter the following commands in the BASIC window: 

merge "Init.asc" 

merge "System. asc" 

merge "Wiremodel-draw. asc" 

merge "Wiremodel-input . asc" 

merge "Shadow-init . asc" 

merge "Shadowing . asc" 



196 



Abacus 8.1 Compiling the Programs 



merge "Service . asc" 

Save the merged program to the main directory (NOT to the modules 
directory) using the command: 

save "tracer :tracer . cmp", a 

Notice the addition of the . cmp extension. This keeps you from 
accidentally overwriting the original code. Exit AmigaB ASIC and start 
the CLI. Delete the modules from the backup disk's modules 
directory, and the backup's modules directory itself. Load the tracer 
source code into a text editor or word processor which has text search 
capabilities, since we have to change a few things in the code to get the 
tracer to compile properly. 

Note: Some of the following changes require deleting lines of source code. 

We found that pressing the apostrophe (<'>) key to make lines into 
remarks is faster than deleting a line of text. So we recommend using 
the <*> key to mark the unnecessary lines as remarks. 

Search for the Rasterlnit : routine. Delete or REM out the 
Screen and two Window commands if your want to be able to size 
the window for multitasking. Deletion of these commands is 
optional. 

Search for the CHAIN command in the LoadEditor: routine and 
change it to END. Or change it to the following: 

CHAIN "tracer :editor . run" 

Next find the three occurrences of the RUN command and replace each 
occurrence with the following two lines: 

CLEAR 

GOTO Startup 

Many compilers have trouble compiling larger program code such as 
the tracer (129K of BASIC source code). The following directions apply 
to the AC/BASIC Compiler, Version 1.3. If you have a newer version 
of this compiler, test compile the original version of the merged 
program to see whether the original command sequences work. 

Bypassing You'll need to make lines in some of the source text's routines inactive. 

routines You have two ways of doing this: Either by making the problem lines 

comments by starting them with apostrophes, or by deleting the lines 
altogether. Search for the SetPoint SUB program, which isn't needed 
by the compiled program. It looks like this: 

SUB SetPoint (xl%,yl%, x2%, y2%, Bright . r, Bright .g, Bright, b) STATIC 
SHARED MaxColour%, Colour () ,RasterHl%,RasterWl%,RastPort& 
SHARED NumberPatternX%,PatternX&,PatternHX() 

IF x2%>RasterWl% THEN x2%=RasterWl% 
'...more code follows... 



197 



8. The Optional Disk 



Amiga 3D Graphic Programming 



CALL RectFillfi (RastPort&,xl%,yl%,x2%,y2%) 

END SUB 

Here are two ways of changing this routine — commenting and deleting: 

' NOTE— all lines commented except label and END SUB 
SUB SetPoint (xl%,yl%, x2%,y2%, Bright. r, Bright .g, Bright, b) STATIC 
SHARED MaxColour%, Colour ( ) , RasterHl%, RasterWl%, RastPort& 
SHARED NumberPatternX%,PatternX&,PatternHX() 

IF x2%>RasterWl% THEN x2%=RasterWl% 
...more code follows... 

CALL RectFill& (RastPort&, xl%, yl%, x2%, y2%) 
END SUB 



' NOTE — lines deleted except label and END SUB 

SUB SetPoint (xl%,yl%, x2%,y2%, Bright. r, Bright .g, Bright. b) STATIC 

END SUB 

The following routines must be deleted or commented out from the 
source text you intend to compile. If you try compiling the program 
without removing the contents of these routines, the program will 
probably crash. 

Use your text editor's search function to find the label, then either delete 
the text between the label and RETURN or END SUB, or add an 
apostrophe to the beginning of each line after the label and before the 

RETURN or END SUB: 

Hardcopy 

Tni tPatternS 

InitPatternX 

StandardFill 

ExtendedFill 



Note: 



Users compiling with AC/BASIC Version 1.2 should remove the 
ScreenLoader subroutine as well as the routines listed above. 



The program will now access the subroutine or SUB program label, 
ignore the deleted/commented text and return to the main program. 
Some of these routines can be replaced by others. For example, if you 
want to print a graphic, use a separate program available for printing 
IFF files. The InitPatternS, InitPatternX, ExtendedFill 
and StandardFill only come into play with patterned 
backgrounds. The speed increase from the compiled program is well 
worth the loss of a patterned background. 

You will also need to change the Background routine, since the 
compiled version of the program deletes any background you might 
generate. Find the label — the code looks something like this: 

Background: 

' Background Determine 
' more code between here and RETURN. . . 
RETURN 



198 



Abacus 



8.1 Compiling the Programs 



Comment out (or delete) the rest of the lines up to the RETURN. Add 
the two lines stated below so the routine looks something like this: 

Background: 

PRINT "Not implemented in compiled version" 

FOR X=l to 3000: NEXT X 

CLS 

' Background Determine 
' more code between here and RETURN. . . 
RETURN 

About The compiled tracer may not add any background to any objects you 

backgrounds create and calculate. The ray tracing calculates properly (i.e., shading 

and colors), but without any background, the "leftovers" of the wire 

model may jut out from the edges of the finished graphic. You have a 

number of options for curing this problem: 

Save the graphic as an IFF file and load it into a program that 
will handle the number of bitplanes you used in computing the 
graphic. Then edit out the jagged edges left from the wire model. 

Configure the original BASIC program to add a default 
background of some sort of solid color, then compile it. 

For Version 1.2 of the AC/BASIC compiler need the following changes. A 

AC/BASIC bug occurs because of the Intuition function called TextLength, 

1.2 users which crashes the 1.2-compiled version from time to time. Replace this 

TextLength function with the following if you are using 

AC/BASIC 1.2: 

PEEKW(rp&+60) *LEN ( .$) 

rp& represents the RastPort passed as the first argument of the 
TextLength function. " . $" represents the string from which the 
length is calculated and passed on the to program as the string's address 
and length. Both commands work identically, provided you avoid 
proportional fonts. 

Now we come to the most irritating error within AC/BASIC 1.2. The 
WINDOW n commands in Scron and Scrof f don't work properly, 
and cause a Guru Meditation number 81000008. Search for the Scron 
and Scrof f SUB programs. Delete WINDOW n from these routines. 

One last problem with the 1.2 compiler. The program occasionally 
crashes when you exit it. Check the RAM disk for any data. This 
concludes the changes for AC/BASIC 1.2 users. 

For all users Save the tracer to the RAM disk and exit the editor to the Workbench. 

Make a backup copy of your AC/BASIC compiler disk. Discard all the 
unnecessary files from this backup to make room (e.g., drawers named 
Chapter, bspread and examples). All you should be able to see 



199 



8. The Optional Disk Amiga 3D Graphic Programming 



in this backup disk's window are the files ac -basic and sort subs. 
Copy your tracer source text from the RAM disk to the backup 
compiler disk. Make sure this disk has at least 230K available (click on 
the disk icon and select the info item from the Workbench menu). 

If the sortsubs program on the is still straight BASIC code, 
compile it before you do anything else. Double-click the sortsubs 
icon. When sortsubs requests the filename, enter tracer, cmp and 
press the <Return> key. When sortsubs requests the location of 
temporary files, press the <Return> key (Yes). This program moves all 
the SUB programs to the end of the source text. 

Once sortsubs ends, double-click the compiler icon. Select the 
following compiler options: 



Long addressing enabled 

Tracer uses ON MENU GOSUBandON MOUSE GOSUB 

Link in the runtime library 

Keep temporary files on the RAM disk (you can do this only if you 
have enough RAM — approximately 1 megabyte) 

The tracer requires at least 50K of extra RAM to compile. Set your 
WORK AREA slider gadget (we chose 54K). 

Click the Compile gadget. You shouldn't get any error messages. 
Exit the compiler and rename the compiled tracer tracer . run. Copy 
the compiled tracer to your copy of the optional disk. 

If everything compiled according to plan, you can now try out the 
tracer. Amiga users with only 512K should open only one screen at a 
time. Now when you load objects and calculate them, the difference 
between compiled and uncompiled programs is like night and day. 

The compiler manual offers some tips for speeding up your programs. 
For example, if you avoid ON...GOSUBS at all costs, this will speed 
things up considerably. Menu reading should be rewritten and ON 
errors avoided. Furthermore, if you define all arrays as STATIC, this 
increases array access by a factor of 6. To do this, you must determine 
the sizes of all arrays, and not change them in the program. Also, all 
arrays must be defined in the main program. If you want to use this, 
you must delete all ERASE commands and put all array definitions in 
the program. For example, set a maximum size of 250 for K ( ) (which 
is enough for all demo objects) and 50 for Mat ( ) . Define all other 
arrays according to definition using numbers, or else the compiler will 
display errors. If you convert the tracer to use STATIC arrays, select 
the U option in the compiler. These methods can increase speed up to 
70%. 



200 



Appendices 



Abacus Appendix A — Modules oe the Tracer 



A • Modules of the Tracer 



1. Initial Routines inlNiT.ASC 

DECLARE FUNCTIONS 

InitMat 

InitPatternS 

InitPatternX 

InitSetPoint 

Rasterlnit 

2. Trace system routines in system. ASC 

Closelt 

Printlt 

EmptyBuf f ers 

Pause 

Box 

DialogBox 

DoDialog 

Rubberbox 

NOOP 

MakeMenu 

DeleteMenu 

MessageEvent 

KeyEvent 

ColorPalette 

ErrorHandling 

Quit 

Scron 

Scroff 

GetString 

GetReal 

Getlnit 

GetKey 

SetCursor see Editor 

PutString 

PutReal 

conrealstr 

constrreal 

Formlnput 
Formlnputlnit 
Formlnput St ring 
Directory 



203 



Appendix A — Modules of the Tracer Amiga 3D Graphic Programming 

3. Wire model routines in WIREMODEL-DRAW . ASC 

Projection 

DrawPlane 

DrawTriangle 

DrawRect angle 

DrawCircle 

DrawCircleSector 

DrawCircleRing 

DrawSphere 

DrawCylinder 

DrawCy Under Segm 

DrawCone 

DrawEllipsoid 

DrawAll 

DrawNew 

HowManyCorners 
Enlargment 

4. Input routines in WIREMODEL- INPUT . ASC 

Initial 
InitialP 

InputP 
InputH 
InputDPH 
InputAngle 

5. Shadow initialization in SHADOW-INIT . ASC 

Init Parameters 

Tranf orm 
InitShadow 

TransformMM 

MinMaxtest 

InitMinMax 

NormAngle 

DeltaSum3 

DeltaSum4 

Getxyzlq 

Getxyzlqk 

DistTest 

ArcTan 



204 



Abacus Appendix A — Modules of the Tracer 



Calcablq 

MMlq3Test 

MMlq4Test 

MMlqKTest 

MMlqkSphere 

MMlqCy Under 

MMlqCone 

MMlqEllipsoid 

InitMinMaxlq 

6. Shadows in SHADOWING. ASC 

IntersectionPointPlane 
Inter sec tionPoint Triangle 
I nt e r sec tionPoint Rectangle 
Inter sec tionPoint Circle 
Anglelntervall 

Inter sect ionPoint Circle Sect or 
Inter sec tionPointCircleRing 
Inter sec tionPoint Sphere 
BasisTrans 

Inter sec tionPointCylinder 
Inter sect ionPointCylinderSegm 
Intersect ionPoint Cone 
Inter sect ionPoint Ellipsoid 

WhichBody 
SetBrightness 

StandardFill 
ExtendedFill 
SetPoint 

Reprojection 
ComputePoint 

Shadows 

7. Service module in service . ASC 

Saver 

Loader 

Merger 

Arraylnit 

LoadMat 

ScreenSaver 



205 



Appendix A — Modules of the Tracer 



Amiga 3D Graphic Programming 



ScreenLoader 

Hardcopy 

LoadEditor 
ClearScreen 

Info 

Help 

Sky 

Fhg 

Background 



206 



Abacus Appendix B — The Tracer Program 



B. The Tracer Program 



The complete tracer program is presented in this appendix as seven 
separate modules. These modules are on the optional diskette in the 
modules directory. If you type in the modules from this appendix, 
type them in one module at a time : you cannot enter the seven modules 
as one unit in AmigaBASIC. Save each module by the specified 
filename and in ASCII format. ASCII files can be easily merged to 
form the final BASIC tracer program, or as a single ASCII file for 
compiling. In addition, each module can be merged into your own 
program code. 

When you're ready to merge the modules, see the merging instructions 
in Section 3.3.2 (page 141). Any changes you must make to the 
modules before compiling should be done from a text editor or word 
processor (see Chapter 8 for compiling suggestions). 

The programs and modules in these appendices contain some BASIC 
lines that must be entered as one line in AmigaBASIC, even though 
they appear on two lines in this book. Formatting the program listings 
to fit into this book has caused some long BASIC lines to be split into 
two lines. To show where a BASIC line actually ends we'll insert an 
end of paragraph (§) character. This marker is not to be entered by you: 
It simply shows when the <Return> key should be pressed in the 
BASIC editor when entering a line. For example, the following line is 
split into two lines in the paragraph below, but must be entered as one 
line in AmigaBASIC, as shown by the H character: 

WinDef NWindow, 100, 50, 460, 150, 32+64+512& , 15&+4096&, 
0&, Title$f 

The U shows the actual end of the BASIC line. 

The following pages contain the listings of the seven modules used to 
make the completed tracer program. 



207 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



The INIT.ASC module 



Init.asc starts 

3-D Graphics! 
f 

Peter Schulz, 1986! 

AMIGA-Version Bruno Jennrich, 19871 
I 

Mainpoint H (hx,hy,hz)! 

Distance to projection point : DPH! 

alpha, beta, gamma : three angle for all three axis! 

=> P(px,py,pz) : Projection point! 
I 

k (n, 0, 0)=Typ: 0=Plane, l=Triangle, 2=Parallelogramm, ! 

3=Circle, 4=Circle segment, 5=Circle arc! 
10=Sphere, 20=Cylinder, 22-Cone, 24=Ellipsoid! 
21=Cylinder segment! 

k(n,0,l)=Reserved! 

k(n, 2, 0)=Radius of the Sphere! 

k (n, 0, 2) ^Material number! 

k (n, l,x) Calculation point! 

k (n, 2, x) =Intersect vector (1,2) or distance vector (3)! 

k (n, 3,x) =Intersect vector (1,2) or distance vector (3)! 

If Typ>=20: (k (n, 2, x) , k (n, 3,x) , k (n, 4, x) ) = Base! 

If Circle segment/arc or cylinder segment:! 

k(n,5,0)=Start angle, k(n, 5,l)=End angle! 

If Circle arc: k (n, 4, 0) =inner Radius [0..1], k (n, 4, 1) =outer Radius [0..1]< 
! 

demo : ! 
DATA 4! 

DATA 10,0,8,0,0,0,50,0,0,0,0,0,0,0,0,0,0,0! 
DATA 2,0,8,80,-30,30,0, 60,0,-10,0,-60,0,0,0,0,0,0! 
DATA 20,0,8,-30,-30,5,25,0,0,0,25,0,0,0,75,0,0,0! 
DATA 10,0,5,30,-30,30,25,0,0,0,0,0,0,0,0,0,0,0! 
! 

••••••••••••••••••••••••••••••••^•••••^ 

* Initial Routine and DATAs *! 

! 
Material:! 
DATA 20! 

DATA 0, .9,0,0,0! 
DATA .6, .6, .6,0, .5! 
DATA .9, .9, .9,0, .8! 
DATA 1,1,1, .1, .9! 
DATA .7,0, .7, .2,0! 
DATA 1,1,1,0,-9! 
DATA 0,0, .5,0,0! 
DATA .8,0,0, .2,0! 
DATA 1,1,1, .2, .2! 
DATA 1,1,1, .2, .1! 
DATA .7, .7,0,0,0! 
DATA 1,1,1,0,1! 
DATA 0, .4, .4, .2,0! 
DATA 1,1,1, .2, .5! 



208 



Abacus 



Appendix B — The Tracer Program 



DATA 1,1,1, .1, .21 

DATA 0, 1,1, 0, 0*31 

DATA 1,1, 1, .05, 011 

DATA .3, .3, .3, .05, 

DATA 1,0,0, .2, .351 

DATA 0,0, 1, .2, .3SI 



5f 



Patterns: <5 

' Number patterns -111 

DATA 10 5 

"SI 

DATA 1 

DATA &HFFFF5 

DATA &HFFFFSI 

DATA &HFFFF SI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFF1 

DATA &HFFFFSI 

DATA &HFFFF! 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFF<JI 

'SI 

DATA 0.0234375SI 

DATA &HFFFFSI 

DATA &HFEFESI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFF<H 

DATA &HFBFBSI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HFFFFSI 

DATA &HEFEFSI 

DATA &HFFFFSI 

DATA &HFFFF1 

DATA &HFFFFSI 

DATA &HBFBFSI 

DATA &HFFFFSI 

DATA &HFFFF1 

'1 

DATA 0.125SI 

DATA &H5555SI 

DATA &HFFFFSI 

DATA &HAAAASI 

DATA &HFFFFSI 

DATA &H5555S1 

DATA &HFFFFSI 

DATA &HAAAASI 

DATA &HFFFFSI 

DATA &H5555SI 

DATA &HFFFFSI 

DATA &HAAAASI 

DATA &HFFFFSI 



209 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



DATA &H55555 
DATA &HFFFF5 
DATA &HAAAA5 
DATA &HFFFF5 

DATA 0.255 
DATA &HFFFF5 
DATA &H55555 
DATA &HFFFF5 
DATA &H5555SI 
DATA &HFFFF5 
DATA &H55555 
DATA &HFFFF5 
DATA &H55555 
DATA &HFFFFSI 
DATA &H55555 
DATA &HFFFF5 
DATA &H55555 
DATA &HFFFFSI 
DATA &H55551 
DATA &HFFFFSI 
DATA &H5555SI 
'5 

DATA 0.3751 
DATA &H55555 
DATA &HBBBB5 
DATA &H55555 
DATA &HBBBB5 
DATA &H55555 
DATA &HBBBB5 
DATA &H55555 
DATA &HBBBB5 
DATA &H55555 
DATA &HBBBB5 
DATA &H55555 
DATA &HBBBB5 
DATA &H55555 
DATA &HBBBB5 
DATA &H55555 
DATA &HBBBB1 
'5 

DATA 0.55 
DATA &H55555 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAASI 
DATA &H55551 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAM 
'5 
DATA 0.6255 



210 



Abacus Appendix B — The Tracer Program 



DATA & HI 1115 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
DATA &H11115 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
DATA &H11115 
DATA &HAAAA5 
DATA &H44 445 
DATA &HAAAA5 
DATA &H11115 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
'5 

DATA 0.755 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
'5 

DATA 0.8755 
DATA &HAAAA5 
DATA &H0000 5 
DATA &H55555 
DATA &H00005 
DATA &HAAAA5 
DATA &H0000 5 
DATA &H55555 
DATA &H00005 
DATA &HAAAA5 
DATA &H0000 5 
DATA &H55555 
DATA &H00005 
DATA &HAAAA5 
DATA &H0000 5 
DATA &H55555 
DATA & HO 00 05 
'5 

DATA 0.97656255 
DATA &H00005 
DATA & HOI 01 5 
DATA &H00005 
DATA &H00005 
DATA &H00005 
DATA &H04045 



211 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



DATA &H0000f 
DATA & HO 00 Of 
DATA &H0000f 
DATA & HI 01 Of 
DATA & HO 00 Of 
DATA & HO 00 Of 
DATA &H0000f 
DATA &H4040f 
DATA &H0000f 
DATA &H0000f 
'f 

DATA If 
DATA &H0000f 
DATA &H0000f 
DATA & HO 00 Of 
DATA &H0000f 
DATA &H0000f 
DATA &H0000f 
DATA &H0000f 
DATA & HO 00 Of 
DATA &H0000f 
DATA & HO 00 Of 
DATA &H0000f 
DATA & HO 00 Of 
DATA &H0000f 
DATA &H0000f 



PatternX:f 

1 Number Fill patterns 

DATA 12f 



If 



DATA Of 
DATA &H0000f 
DATA &H0000f 
DATA £ HO 00 Of 
DATA & HO 00 Of 
DATA &H0000f 
DATA & HO 00 Of 
DATA &H0000f 
DATA &H0000f 
DATA & HO 00 Of 
DATA & HO 00 Of 
DATA &H0000f 
DATA & HO 00 Of 
DATA & HO 00 Of 
DATA SHOOOOf 
DATA & HO 00 Of 
DATA &H0000f 
'f 

DATA 0.00390625f 
DATA &H8000f 
DATA & HO 00 Of 
DATA &H0000f 
DATA & HO 00 Of 
DATA & HO 00 Of 
DATA &H0000f 
DATA & HO 00 Of 
DATA & HO 00 Of 
DATA &H0000f 
DATA &H0000f 



212 



Abacus Appendix B — The Tracer Program 



DATA &H0000f 
DATA SHOOOOf 
DATA & HO 00 0^1 
DATA &H0000fl 
DATA &H0000fl 
DATA &H0000A 
'11 

DATA 0.0078125SI 
DATA &H8000A 
DATA & HO 00 0^1 
DATA &H0000A 
DATA & HO 00 Of 
DATA &H0000fl 
DATA & HO 00 Of 
DATA &H0000A 
DATA SHOOOOf 
DATA &H0080f 
DATA &H0000A 
DATA &H0000f 
DATA &H0000A 
DATA &H0000SI 
DATA &H0000SI 
DATA &H0000SI 
DATA &H0000SI 

DATA 0.015625SI 
DATA &H8080fl 
DATA & HO 00 Of 
DATA &H0000A 
DATA &H0000f 
DATA &H0000A 
DATA &H0000A 
DATA &H0000A 
DATA & HO 00 0^1 
DATA &H8080fl 
DATA SHOOOOfl 
DATA & HO OOfl 
DATA SHOOOOfl 
DATA &H0000A 
DATA &H0000A 
DATA &H0000A 
DATA SHOOOOfl 

DATA 0.03125SI 
DATA &H8080A 
DATA &H0000A 
DATA &H0000SI 
DATA &H00005 
DATA &H0808SI 
DATA &H0000SI 
DATA &H0000SI 
DATA & HO 00 0^1 
DATA &H8080SI 
DATA &H0000SI 
DATA & HO 00 0^1 
DATA &H0000SI 
DATA &H0808A 
DATA &H0000SI 
DATA SHOOOOfl 
DATA SHOOOOfl 



213 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



DATA 0.0625$ 
DATA &H8888$ 
DATA &H0000$ 
DATA &H0000$ 
DATA & HO 000$ 
DATA &H8888$ 
DATA &H0000f 
DATA &H0000$ 
DATA &H0000$ 
DATA &H8 888$ 
DATA &H0000$ 
DATA & HO 00 0$ 
DATA & HO 000$ 
DATA &H8888$ 
DATA & HO 000$ 
DATA &H0000$ 
DATA &H0000$ 

$ 
DATA 0.125$ 
DATA &H8888$ 
DATA &H0000$ 
DATA &H2222$ 
DATA &H0000$ 
DATA &H8888$ 
DATA &H0000$ 
DATA &H2222$ 
DATA &H0000$ 
DATA &H8888$ 
DATA &H0000$ 
DATA &H2222$ 
DATA &H0000$ 
DATA &H8888$ 
DATA &H0000$ 
DATA &H2222$ 
DATA & HO 000$ 
'$ 

DATA 0.1875$ 
DATA &H8888$ 
DATA &H22221 
DATA &H8888$ 
DATA &H0000$ 
DATA &H2222$ 
DATA &H8888$ 
DATA &H2222$ 
DATA &H0000$ 
DATA &H8888$ 
DATA &H2222$ 
DATA &H8888$ 
DATA &H0000$ 
DATA &H2222$ 
DATA &H8888$ 
DATA &H2222$ 
DATA &H0000$ 
'$ 

DATA 0.25$ 
DATA &HAAAA$ 
DATA &H0000$ 
DATA &HAAAA$ 
DATA &H0000$ 



214 



Abacus Appendix B — The Tracer Program 



DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA ZHOOOOf 
DATA &HAAAA5 
DATA &H00005 
DATA &HAAAA5 
DATA &H00005 

DATA 0.31255 
DATA &HAAAA5 
DATA &H11115 
DATA &H44445 
DATA &H11115 
DATA &HAAAA5 
DATA &H11115 
DATA &H44445 
DATA &H11115 
DATA &HAAAA5 
DATA &H11115 
DATA &H44445 
DATA &H11115 
DATA &HAAAA5 
DATA &H11115 
DATA &H44445 
DATA &H11115 
'5 

DATA 0.3755 
DATA &hAAAA5 
DATA &H11111 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
DATA &H11115 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
DATA &H11115 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
DATA &H11115 
DATA &HAAAA5 
DATA &H44445 
'5 

DATA 0.43755 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAA5 
DATA &H44445 
DATA &HAAAA5 
DATA &H55555 



215 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



DATA &HAAAA5 
DATA &H4444A 
DATA &HAAAA5 
DATA &H55555 
DATA &HAAAA$ 
DATA &H4444A 

DATA 0.55 

DATA &HAAAAA 

DATA &H5555A 

DATA &HAAAA5 

DATA &H55555 

DATA &HAAAA1 

DATA &H55555 

DATA &HAAAAA 

DATA &H5555SI 

DATA &HAAAAf 

DATA &H5555A 

DATA &HAAAA5 

DATA &H5555f 

DATA &HAAAAf 

DATA &H55555 

DATA &HAAAASI 

DATA &H55555 

«i 

StartUp:f 

CHDIR "Tracer :libs M Sl 

1 

DECLARE FUNCTION SetRastO LIBRARYSI 
DECLARE FUNCTION SetRGB4() LIBRARY^ 
DECLARE FUNCTION GetRGB4%() LIBRARY^ 
DECLARE FUNCTION SetDrMdO LIBRARYSl 
DECLARE FUNCTION SetAPenO LIBRARY^ 
DECLARE FUNCTION SetBPenO LIBRARYSI 
DECLARE FUNCTION Move() LIBRARYSI 
DECLARE FUNCTION Draw() LIBRARYSI 
DECLARE FUNCTION WritePixel () LIBRARY^! 
DECLARE FUNCTION RectFill () LIBRARYSl 
DECLARE FUNCTION Text() LIBRARYSI 
DECLARE FUNCTION TextLength& ( ) LIBRARYSI 
LIBRARY "graphics, library'"]! 

SI 
DECLARE FUNCTION SetWindowTitles () LIBRARY^ 
DECLARE FUNCTION ScreenToFront ( ) LIBRARY^ 
DECLARE FUNCTION ScreenToBack () LIBRARY^ 
DECLARE FUNCTION ActivateWindow () LIBRARY^! 
DECLARE FUNCTION RemakeDi splay ( ) LIBRARY^! 
LIBRARY "intuition, library"^! 

DECLARE FUNCTION AllocMem&() LIBRARYSI 
DECLARE FUNCTION FreeMemO LIBRARYl 
DECLARE FUNCTION AllocSignal% ( ) LIBRARY^ 
DECLARE FUNCTION FindTask& () LIBRARYSI 
DECLARE FUNCTION DoIO& () LIBRARY^ 
DECLARE FUNCTION OpenDevice& LIBRARY^ 
LIBRARY "exec.library"SI 
1 

DECLARE FUNCTION xOpen& LIBRARYSI 
DECLARE FUNCTION xRead& LIBRARY1 
DECLARE FUNCTION xWrite& LIBRARYSI 



216 



Abacus Appendix B — The Tracer Program 



LIBRARY "dos. Library"*!! 
SI 

DEF FN Xscale (x) = (x+Picturex) *Picturewidthf 

DEF FN Yscale (y) = (Picturey-y) *PictureheightSI 

DEF FN Xresc (x) =x/Picturewidth-Picturexf 

DEF FN Yresc (y) =Picturey-y /Pictureheightf 
f 

1 Value of determinante with the vectors a,b and c:f 

DEF FN Det (Al,Bl,Cl,A2,B2,C2,A3,B3,C3)=Al* (B2*C3-C2*B3) -Bl* (A2*C3- 
C2*A3) + C1* (A2*B3-B2*A3) f 
SI 

1 Cosine of the angle between vector a and Vector b:f 

DEF FN 
CosinAngle (ax, ay, az, bx, by, bz) = (ax*bx+ay*by+az*bz) /SQR ( (ax*ax+ay*ay+az*az) * (bx*bx+by 
*by+bz*bz) ) SI 
SI 

' Radiant to Degree: SI 

DEF FN Deg(a) =a*180/Pif 

SI 

1 Degree to Radiant: SI 

DEF FN Rad(a)=a*Pi/180f 
SI 

True = If 

False = NOT (True) SI 
SI 

1 Search depth for calculation pointSI 

MaxStack% = 1 9 SI 

SI 

Pi - 3.141592654#f 

Pd2 = Pi/2SI 

Pm2 = 2*Pif 

SI 

Threshold - .0001SI 
SI 

Hx = OSI 

Hy = Of 

Hz = f 

SI 

Px = 500SI 

Py = Of 

Pz = Of 
f 
' Picture drawn after first call of new drawingf 

Newone! = Truef 
f 

1 Wait in New Drawing mode for key or mousef 

WaitFlg! = Truef 
f 

1 All Menu points active?f 

Start% = Of 

f 

DIM Stack(MaxStack%,2)f 

DIM RestLght (MaxStack%)f 
f 

' Arrays for ERASE added to systemf 

DIM Help(O) f 

DIM minmax% (0) f 

DIM minmaxlq(O) f 

DIM K(0)f 



217 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



' Default-Object load: SI 
SI 

'RESTORE demo! 
'READ MaxNumberSI 
1 Number K=MaxNumber SI 
'FOR n% = l TO NumberKSI 
FOR p%=0 TO 51 
FOR q% = TO 2SI 

READ K(n%,p%,q%)SI 
NEXT q%SI 
NEXT p%SI 
'NEXT n%SI 
SI 

' How many angles needed to compute in a circle ?SI 
Number Segments = 4 SI 
f 

' Where is the light source ?SI 
Qx=1000&SI 
Qy=1000&SI 
Qz=1000&Sl 
SI 

' Light source color: whiteSI 
Qh.r-lSI 
Qh.g-lSI 
Qh.b=lSI 
SI 

' Fill pattern = StandardSI 

1 Only need in case of SetPoint. OSSetPoint has its own pattern! SI 
PatternArt%--=OSI 
SI 

1 Point size for shadowsSI 
BoxW%=lSI 
BoxH%=l SI 
Si 

! Actual DriveSI 
ActDrive$ - "tracer: "SI 
CHDIR ActDrive$SI 
SI 

GOSUB CpenGfxSI 

GOSUB Baste rln it SI 
SI 

1 S h a d o w w i n d o w (Default)SI 

XStart%=OSI 

YStart^-OSI 

XEnd%--RasterWl%SI 

Yend%-R«isterHl%SI 
SI 

Picturewidth=FactorX ' for enlargingSI 

Pi ct ; j reheignt=FactorYSI 

Picturex=RasterW2% / PicturewidthSI 

Picturey=RasterH2% / PictureheightSI 

SI 

GOSUB InitMatSI 

GOSUB InitPatternS SI 

GOSUB InitPatternXSI 

GOSUB InitialPSl 
SI 

GOSUB MakeMenuSI 
REM remove after testing SI 



218 



Abacus Appendix B — The Tracer Program 



REM ON ERROR GOTO ErrorHandling! 
! 

ok: ' Main loop! 

MENU ONI 
WHILE 1! 

ON MENU GOSUB MessageEvent! 
GOSUB KeyEvent! 
WEND! 
'! 
InitMat :! 

' Initial material brightness! 
' mat(n, 0) = Red material brightness! 
1 mat(n, 1) = Green material brightness! 
' mat(n,2) = Blue material brightness! 
' mat(n, 3) = Factor for unlit /shadow! 
' mat(n, 4) = Factor for mirroring! 

' mat (n, 5) = Factor for Transparecy, not implemented! 
• mat (n, 6) = reserved! 
RESTORE Material! 
READ NumberMat! 
DIM Mat (NumberMat, 6)! 
FOR n%=l TO NumberMat! 
FOR m%=0 TO 4! 

READ Mat (n%,m%)! 
NEXT m%! 
NEXT n%! 
RETURN! 
'! 
InitPatternS:! 

1 Initialize fill pattern (Standard)! 
RESTORE Patterns! 
READ NumberPatternS% ! 
! 

DIM PatternHS (NumberPatternS%) ! 

PatternS& = AllocMem& ( (NumberPatternS%+l) *2*16, 65536& + 2) ! 
IF PatternS& = THEN! 
CLS! 

CALL DialogBox ("No free Chip-Memory !!!", 1, True, xla%, yla%, x2a%, y2a%, False) ! 
CALL DoDialog(n% / 1,-1,-1,-1, -1 , xla%, yla%, x2a%, y2a%, -1 , -1, -1,-1)! 
GOSUB Closelt! 
END! 
END IF! 

! 
FOR i%=0 TO NumberPatternS%! 
READ PatternHS (i%)! 
FOR j%=0 TO 15! 

READ TempPattern%! 

POKEW (PatternS&+i%*32+j%*2) , TempPattern%! 
NEXT j%! 
NEXT i%! 
RETURN! 
'! 
InitPatternX:! 

1 Initialize fill pattern (Extended)! 
RESTORE PatternX! 
READ NumberPatternX%! 
! 

DIM PatternHX(NumberPatternX%*2)! 

PatternXS = AllocMemS ( (NumberPatternX%*2+l ) *2*16, 65536& + 2) ! 

IF PatternX& = THEN! 



219 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



CLS! 

CALL DialogBoxC'No free Chip-Memory !!!", 1, True,xla%,yla%,x2a%, y2a%, False) ! 
CALL DoDialog(n%,l,-l,-l,-l,-l,xla%,yla%,x2a%,y2a%, -1,-1, -1,-1)1 
GOSUB Closelt! 
END! 
END IF! 

FOR i%=0 TO NumberPatternX%! 
READ PatternHX(i%)! 

PatternHX(NumberPatternX%*2-i%)= 1 - PatternHX (i%) 1 
FOR j%=0 TO 151 

READ TempPattern%! 

POKEW (PatternX&+i%*32+j%*2) ,TempPattern%! 

POKEW (PatternX&+NumberPatternX%*2*32-i%*32+j%*2) ,NOT (TempPattern%) 1 
NEXT j%! 
NEXT i%! 
RETURN! 
«! 
InitSetPoint:! 

1 Read assembler routine for Point-drawing:! 
! 

REM read binary data: I 
! 

OPEN "I",#l, "Tracer :SetPoint.B"! 
SetPointNum&=LOF (1)1 

SetPointAdr& = AllocMemS (SetPointNumS , 65536&+2) 1 
1 

IF SetPointAdr&=0 THEN! 
CLOSE #11 
GOSUB Closeltl 
END! 
END IF! 
! 

FOR n%=0 TO SetPointNum&\2-l! 
h%=CVI (INPUT$ (2,#1) )! 
POKEW SetPointAdr&+2*n%,h%! 
NEXT n% ! 

! 

CLOSE #1! 
! 

REM subroutine call addresses:! 
! 

LET OSOpenGfx&=SetPointAdr&! 
LET OSCloseGfx&=SetPointAdr&+&HlE! 
LET OSSetPoint&=SetPointAdr&+&H38! 
1 

REM Addresses of the variables:! 
! 

LET OSColour&=SetPointAdr&+&H3F8! 
LET OSMaxColour&=SetPointAdr&+&H27A! 
LET OSModus&=SetPointAdr&+&H27C! 
LET OSRastPort&=SetPointAdr&+&H276! 
LET OSRasterWl&=SetPointAdr&+&H27E! 
LET OSRasterHl&=SetPointAdr&+&H280! 
RETURN! 
•1 
OpenGfx:! 

CALL OSOpenGfx&! 
RETURN! 
'! 
CloseGfx:! 



220 



Abacus Appendix B — The Tracer Program 



CALL OSCloseGfx&1 
RETURNSI 
'1 
Rasterlnitrl 

' Select resolution and display mode 1 

WINDOW CLOSE 2 ' deleter any windows arril 

SCREEN CLOSE 1 ' screens SI 
SI 

WINDOW 1, H ", (0, C) - (631 , 185) , 6 ' new window with Sta tus-1 inel 
SI 

'PALETTE 0,0,0,0 ' Colour for user screenSl 

'PALETTE 1,1,1,1 Sf 

'PALETTE 2, .4, .4,11 
SI 

NWBase& = WINDOW (7) SI 

NRastPortS = WINDOW (8) St 

NWScreenfi = PEEKL (NWBase&+4 6) SI 

1 Base address of Window-St ructureSI 

' from which the screen structure is takenSI 

' RastPort belongs with the WINDOW () functional 
SI 

Status$ =■ " Status: Select resolution"^ CHR$ (Q) ' Status line outputSI 

dummy = SetWindowT.lt les (NWBase&, SACD (St. atus$) , 0) SI 
SI 

DisplayNI$ (0) - " Normal "SI 

DisplayM$(l) = " Hold and Mooify"SI 

DisplayM$(2) - " Extra Ha 1 fbri te"1 

SI 

XResl$(0) ■= " Norma i"1 

XResl$(l) = " HIKES "SI 



YResl$(0) - " Normal 


" S( 


YResl$(l) ■•-- " r.ntcrlac: 


-i"1 


SI 




x(0) - 0:x(l) -- 0:x (2) 


^ C:x(3) -- 4 Si 


' Which values or strir 


vas at which posit: 


SI 




y = 0SI 




' topmost line? = Start 


iineSi 


SI 




Modulo (0) - 3 SI 




Modulo (1) --- 21 




Modulo (2) - 2 SI 




Modulo (3) - 6SI 




' How many values for * 


jach selection lit 


Tl 




COLOR I SI 





Colours (0) = ITl 
Colours (1) = 2SI 
Colours (2) = 2 SI 
Colours (3) - 2 SI 

' First line -> white rest of the lines -> blueSI 
SI 
Outg:SI 

LOCATE 1.0,211 

COLOR Colours (0) 1 

PRINT "Display mooe : " ; Di spIayMS (x (C) ) 1 

LOCATE 12,21.1 

COLOR Colours (1)1 



221 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



PRINT "X-Resolution : ";XResl$ (x (1) ) SI 

LOCATE 14,21^1 

COLOR Colours (2) SI 

PRINT "Y-Resolution : "; YResl$ (x (2) ) SI 

LOCATE 16,24fl 

COLOR Colours (3) SI 

PRINT "BitPlanes : ";x(3)+lSI 

SI 
Waiter: a$ = INKEY$SI 
IF a$ = "" THEN WaiterSI 
SI 

IF a$ = CHR$(30) THEN x(y) = (x(y)+l) MOD Modulo (y) SI 
IF a$ - CHR$(31) THEN x (y) = x (y) -1 SI 
■ CRSR Left /Rights 

IF x(y) < THEN x (y) = Modulo (y) -15 
IF a$ = CHR$(28) THEN SI 

Colours (y) = 21 

y = y-lSI 
END IFSI 
' CRSR UpSI 

IF a$ = CHR$(29) THENSI 

Colours (y) = 2 SI 

y = (y + 1) MOD 4SI 
END IFSI 
« CRSR DownSI 
SI 
IF y<0 THEN y=3SI 

Colours (y) = 1SI 

IF (x(0) > 0) AND (y=0) THENSI 

x(l) = ' Select HAM or Halfbrite SI 

x(3) = 5 ' 5+1 BitPlanesSI 

Modulo (3) = 6SI 
END IFSI 
SI 

IF x(0)>0 THEN x(3) =5 ' Number of BitPlanes unchanged by HAM orSI 

' Halfbrite modeSI 
51 
IF (x(0) = 0) AND (x(l)Ol) THEN SI 
Modulo (3) = 5SI 

IF x(3) > 4 THEN x(3) = 4 ' Maximum 4 + 1 BitPlanesSI 
END IF ' in Normal ModeSI 

SI 
IF (x(l) = 1) AND (y = 1) THENSI 

x(0) = ' HIRES and NormalSI 

IF x(3)>3 THEN x(3) = 3 ' Maximum 3 + 1 BitPlanes SI 
Modulo (3) = 4SI 
END IFSI 

IF a$<> CHR$(13) THEN GOTO OutgSI 

COLOR If 

SI 

RasterW%= (x (1) +1) *320SI 

RasterH%=(x(2) +1) *200 '256 for PAL-resolutionSI 

IF x(0) =1 THEN Modus% = &H800 ' HAM SI 



222 



Abacus Appendix B — The Tracer Program 



IF x(0) =2 THEN Modus% = &H80 'HalfBriteSI 
IF x(l) =1 THEN Modus% = &H8000 ' HIRESSI 

• (HAM, Halfbrite) and HIRES close the same way SI 
SI 

IF x(2) =1 THEN Modus% = Modus% OR 4 ' LAC ESI 
SI 
CLSSI 

RasterT% = x(3)+lf 
SI 
IF RasterT% = 6 THEN RasterT% - 5SI 

' If HAM, open a normal screen SI 

1 (max. 5 BitPlanes) SI 
SI 
IF FRE(-l) < (RasterW%/8*RasterH%*RasterT%)+5000 THENSI 

CLSSI 

CALL Printlt ("Insuf f icent memory for bitmap !!!", 100, False) SI 

CALL Printlt ("Please try a lower resolution or number of bitmaps 
! ! !",130,False)SI 

SI 

CALL DialogBox ("Ok", 1, True, xlb%, ylb%, x2b%,y2b%, False) SI 

CALL DoDialog(n%,l,-l,-l,-l,-l,xlb%,ylb%,x2b%,y2b%, -1,-1, -1,-1) SI 

CLSSI 

GOTO OutgSI 
END IFSI 

SI 
SCREEN !,RasterW%,RasterH%,RasterT%,x(l)+(x(2) *2)+lSI 

1 Width , Height , Depth , Mode SI 
SI 
WINDOW 2, "", (0,0)-(RasterW%-9,RasterH%-15) ,0,1SI 

' Window layer SI 
SI 
RasterT% = x(3)+lSI 

' old RasterT valueSI 
SI 

WBaseS = WINDOW (7) SI 
WScreenS = PEEKL (WBaseS + 4 6) SI 

1 Extract address of the new screen from window addrressSI 
SI 
POKEL WBases+24,SHl00 OR &H800 OR 65536SSI 

1 Window Flags change: Borderless, RBMTrap, NoCareRef reshSI 
SI 

Viewports - PEEKL (WBase&+ 4 6) + 44SI 
ColorMapS = PEEKL (Viewport Sf 4) SI 
RastPort& = ViewportS + 40SI 
BitMapS - WScreenS + 184SI 
SI 

Adr = PEEKL (RastPortS+4) +8 ' BitPlanes for loadingSI 

FOR i = TO RasterT-%-1 ' and savingSI 

BitP lanes & (i) - PEEKL (Adr+4*i) SI 
NEXT iSI 
SI 

BitPlane6& = BitMap&+28SI 

1 Where do you want the sixth bitplane address placed ?SI 
SI 
Depths = BitMapS + 5SI 

1 Where do you want the new depth placed ?SI 
SI 

CALL SetRastS (RastPortS, 0) SI 
CALL SetRGB4& (Viewports, 1 , 15, 15, 15) SI 
CALL SetRGB4s (Viewports, 0, 0, 0, 0) SI 



223 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



1 Clear new screen and set background SI 
SI 
IF RasterT% = 6 THENSI 

RSize& = RasterW%* (RasterH%\8) SI 

Flags& = 6553 6&+2 ' MEMF_CHIP I MEMF_CLEARSI 

Mem& = AllocMem& (RsizeS, Flags&) SI 
IF Mem& = THENSI 
CALL ScroffSI 

CALL Printlt ("Not enough memory for sixth BitPlane !!!", 100, False) < 
CALL DialogBox ("Sorry !", 1, True, xla%, yla%, x2a% , y2a%, False) SI 
SI 

CALL DoDialog(n%,l,-l,-l,-l,-l,xla%,yla%,x2a%,y2a%, -1,-1, -1,-1) SI 
GOSUB CloseltSI 
RUN SI 
END IFSI 
SI 

POKE Depths, 6SI 
1 New depthSI 
SI 

POKEL BitPlane6&,Mem&SI 
BitPlanesS (5) =Mem&SI 

1 Poke address of the sixth BitPlaneSI 
SI 
POKEW Viewport& + 32,Modus%SI 

1 Poke for display mode POKENSI 
SI 

dummy = RemakeDi splay (dummy &) SI 
1 compute new display SI 
END IF SI 
SI 

Status$ = " Status: Initializing"+CHR$ (0) SI 
CALL SetWindowTitles& (NWBase&, SADD (Status?) , 0) SI 
SI 

CALL ScroffSI 

CALL SetDrMds (RastPorti., 1) I 

SI 
RasterWl% - RasterW%-l ' 319/639SI 
RasterHl% - RasterH%-l ' 199/399SI 
RasterW2% = RasterW%/2 ' Screen middleSI 
RasterH2% - RasterH%/2SI 
SI 

FactorX - (x(l)+l)/2SI 
FactorY = (x(2)+l)/2SI 
1 

POKEW OSModus&,Modus%SI 
POKEL OSRastPort&,RastPort&SI 
POKEW OSRasterWl&,RasterWl%SI 
POKEW OSRasterHl&,RasterHl%SI 
SI 

MaxColour% = 2 /v RasterT%SI 
IF (RasterT% = 6) THENSI 

IF (Modus% AND &H800) = &H800 THEN SI 

MaxColour% - 16 ' HAM SI 

ELSESI 

MaxColour% = 64 ' HalfbriteSI 

END IFSI 
END IFSI 
SI 

POKEW OSMaxColour&,2 A RasterT% 'If HAM: 64 Colour! SI 
DIM Colour (MaxColour%,3)SI 



224 



Abacus 



Appendix B — The Tracer Program 



FOR m%=0 TO 35 
Colour (l,m%)=0 
Colour (2, m%)=l 

NEXT m%5 



'Blackf 
'Whitef 



IF (Modus% AND &H80) 
MF%=MaxColour%/25 



&H80 THEN ' HalfBrite5 



Colour (MF%+1, 0) =MF%5 
Colour (MF%+2, 0) =MF%+15 
FOR m%=l TO 35 

Colour (MF%+1, m%) -05 
Colour (MF%+2 ,m%) =.55 
NEXT m%5 

RESTORE OptimaleHBColour5 
ELSE 5 

MF%=MaxColour%5 
RESTORE OptimaleColour5 
END IF5 
5 

FOR n% = 3 TO MF%5 
READ r%,g%,b%5 
5 

Colour (n%,0)=n%-15 
Colour (n%,l)=r%/155 
Colour (n%, 2) =g%/155 
Colour (n%, 3) =b%/155 

CALL SetRGB4& (Viewport &, n%-l, r%, g%, b%) 5 
5 

IF (Modus% AND &H80) <>0 THEN 'HalfBrite5 

Colour (n%+MF%, 0) =n%+MF%5 
FOR m%=l TO 35 

Colour (n%+MF%, m%) = (INT (Colour (n%, m%) *15) \2) /155 
NEXT m%5 
END IF5 
5 

NEXT n%5 

1 => Colour (11,0) = color index, 5 
' Colour (n, 1. . 3) = RGB brightness5 
5 

1 Poke colors into assembler routines array:5 
5 

FOR n%=0 TO MaxColour%-15 

POKEW OSColour&+n%*8, Colour (n%+l,0)5 
FOR m%=l TO 35 

POKEW OSColour&+n%*8+m%*2, Colour (n%+l,m%) *10245 
NEXT m%5 
NEXT n%5 
CLS5 
RETURN5 



OptimaleHBColour: 
DATA 10,0,05 
DATA 0,10,05 
DATA 0,0,105 
DATA 10, 10, 05 
DATA 10,0,105 
DATA 0,10,105 
DATA 10,10,105 



'HalfBrite5 



225 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



DATA 15,10,05 

DATA 15,0,105 

DATA 15,10,105 

DATA 10,15,05 

DATA 0,15,105 

DATA 10,15,105 

DATA 0,10,155 

DATA 10,0,155 

DATA 10,10,155 

DATA 15,15,105 

DATA 15,10,155 

DATA 10,15,155 

DATA 13,13,135 

DATA 8,8,85 

DATA 8,0,05 

DATA 0,8,05 

DATA 0,0,85 

5 

' and the next six Colours^ 

5 

OptimaleColour : 5 

DATA 15,0,05 

DATA 0,15,05 

DATA 0,0,155 

DATA 15,15,05 

DATA 15,0,155 

DATA 0,15,155 

DATA 7,0,05 

DATA 0,7,05 

DATA 0,0,75 

DATA 7,7,05 

DATA 7,0,75 

DATA 0,7,75 

DATA 7,7,75 

DATA 15,7,05 

DATA 15,0,75 

DATA 15,7,75 

DATA 7,15,05 

DATA 0,15,75 

DATA 7,15,75 

DATA 0,7,155 

DATA 7,0,155 

DATA 7,7,155 

DATA 15,15,75 

DATA 15,7,155 

DATA 7,15,155 

DATA 3,3,35 

DATA 10,10,105 

DATA 10,0,05 

DATA 0,10,05 

DATA 0,0,105 

'5 

'end of INIT.ASC5 



226 



Abacus Appendix B — The Tracer Program 



The SYSTEM.ASC module 



SYSTEM. ASC start SI 

* Trace-System-Routines *SI 

*******************************************<§ 

SI 
CloseIt:SI 

' Close all and free memorySI 

GOSUB CloseGfxSI 

WINDOW CLOSE 2 SI 

SCREEN CLOSE 1 ' automatic release of allocated 6th bitmapSI 

MENU RESET ' SI 
SI 

IF SetPointAdr& <> THEN CALL FreeMemS (SetPointAdrS, SetPointNumS) SI 

IF PatternSS <> THEN CALL FreeMemS (PatternSS, (NumberPatternS% + l ) *2*16) SI 

IF PatternXS <> THEN CALL FreeMemS (PatternXS, (NumberPatternX%*2+l ) *2*1 6) SI 
'Save pattern and release ASSEM-RoutineSI 

LIBRARY CLOSESI 
RETURN SI 

SI 
SUB Printlt (Out$, y%, Scr) STATICSI 
SHARED RastPortS,NRastPortS,RasterW2%, True, LengthsSI 

1 Centered text output on one of the two screens SI 

' Out$: Printed stringSI 

• y% : verticle Position ?SI 

1 Scr: User or Display Screen?SI 

IF Scr = True THENSI 
rpS = RastPort&SI 
Middles = RasterW2%SI 
1 write to new (Display) ScreenSI 

ELSESI 

rp& = NRastPort&SI 

Middles = 320 ' User-Screen (NO OP Window) SI 

END IFSI 

Lengths = Text Lengths (rp&, SADD (Out$) , LEN (Out$) ) SI 

Middles = Middles - Lengths/2SI 

CALL Moves (rp&, Middles, CLNG (y%) ) SI 

CALL Texts (rpS , SADD (Out$) , LEN (Out$) ) SI 
END SUBSI 
'SI 
SUB EmptyBuffers STATICSI 

1 clear mouse and keyboard buffer SI 

WHILE MOUSE (0) <> OSI 

WENDSI 

WHILE (INKEY$<>"")SI 

WENDSI 
END SUBSI 
'SI 
Pause: SI 

1 Wait for (Mouse-) key pressSI 

CALL EmptyBuffers ' clear buffer SI 

WHILE (INKEY$ = "") AND (MOUSE (0) = 0)SI 

WENDSI 
RETURNSI 



227 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



SUB Box(RastPort&,xl%,yl%,x2%,y2%) STATIC! 

1 rectangle in Display-Screen! 

1 RastPort&: draw in which RastPort ! 

1 xl,yl,x2,y2 coordinates of the rectangle! 

CALL Moves (RastPort&,xl%,yl%) 1 

CALL Draws (RastPort&,x2%,yl%) 1 

CALL Draws (RastPortS,x2%,y2%) ! 

CALL Draws (RastPortS,xl%,y2%) ! 

CALL Draws (RastPortS, xl%, yl%+l) ! 
END SUB! 
'! 

SUB DialogBox (Dial og$, Posit ion%, Ret, xl%, yl%, x2%, y2%, Scr) STATIC! 
SHARED RastPortS, NRastPortS, True, RasterWl%,RasterW2%! 
Create your own requester! 
Dialog$ = Text in Dialog Box"! 
Position% ! 

= rights 

1 = center! 

2 = left! 
Ret% = can you press <Return>?! 

True = Yes! 
False = No! 
xl%,yl%,x2%,yl% = Size of • click 1 -Field (word returned)! 
Scr = In which screen output ?! 
True = Display-Screen! 
False = User-Screen! 
II 
IF Scr = True THEN! 
rpS = RastPorts! 
Middles - RasterW2%! 
SEnds = RasterWl%! 
' Write to Display-Screen! 
ELSE! 

rpS = NRastPorts! 
Middles = 320! 
SEnds = 64 0! 

1 RastPort of Basic Windows! 
END IF! 
H 
yl% = 150! 
y2% = 150 + 6 + 10! 
I 

Lengths = TextLengths (rpS , SADD (Dialog$) , LEN (Dialog$) ) ! 
II 

IF Position% = THEN ! 
xl% = 70! 

x2% - xl% + Lengths + 20! 
END IF! 
I 

IF Position% = 1 THEN! 

xl% = MiddleS-LengthS/2-10! 
x2% = MiddleS+LengthS/2+10! 
END IF! 
I 

IF Position% = 2 THEN ! 

xl% = SEnds-70-20-10-Lengths! 
x2% = SEndS-70-10! 
END IF! 



228 



Abacus Appendix B — The Tracer Program 



CALL Move& (rp&, xl%+10, yl%+10) 1 
CALL Texts (rp&, SADD (Dialog$) , LEN (Dialog$) ) 1 
SI 

IF Scr = True THENSI 

CALL Box(rp&,xl%,yl%,x2%,y2%)SI 
CALL Box(rp&,xl%-4,yl%-2,x2%+4,y2% + 2)SI 

IF Ret = True THEN CALL Box (rp&, xl%-2, yl%-l, x2% + 2, y2% + l ) SI 
ELSESI 

LINE (xl%,yl%)-(x2%,y2%) ,,bSI 
LINE (xl%-2,yl%-2)-(x2%+2,y2%+2) , , bSI 

IF Ret = True THEN LINE (xl%-l ,yl%-l) - (x2%+l, y2% + l ) , , bSI 
END IFSI 
END SUBSI 
'SI 

SUB DoDialog(n%,Ret%,xla%,yla%,x2a%,y2a%,xlb%,ylb%,x2b%,y2b%,xlc%,ylc%,x2c%,y2c%) 
STATICS 

1 Dialog box readSI 

1 n%: which gadget clicked ?SI 

1 Ret%: which gadget specified by pressing <Return>?SI 

1 xl. , yl . , x2. , y2. coordinates of the boxSI 

CALL EmptyBuffersSI 

n% = -If 

WHILE (n% = -1)1 

IF MOUSE (0) <> THENSI 
x = MOUSE (1) SI 
y = MOUSE (2) SI 
SI 

IF (xla%<x) AND (x2a%>x) AND (yla%<y) AND (y2a%>y) THEN n% = OSI 
IF (xlb%<x) AND (x2b%>x) AND (ylb%<y) AND (y2b%>y) THEN n% = 1 SI 
IF (xlc%<x) AND (x2c%>x) AND (ylc%<y) AND (y2c%>y) THEN n% = 2 SI 
END IFSI 

IF INKEY$ = CHR$(13) THEN n% = Ret%SI 
WENDf 
END SUBSI 
'SI 

SUB Rubberbox( x%, y%, w%, h%, Back!) STATICSI 
SHARED 

RasterWl%,RasterHl%,WScreen&,NRastPort&,RastPort&,NWScreen&, NWBaseS, WBaseS , Lengths, 
True,FalseSI 

1 Make rectangle with mouseSI 
1 x%,y%: upper left cornerSI 
■ w%,h%: Width, HeightSI 
1 Back! : Return to user window ?SI 
CALL ScronSI 

CALL SetDrMdS (RastPortS, 2) 'COMPLEMENT SI 
SI 

CALL SetAPenS (RastPortS, 1) SI 
SI 
Repitition:SI 
Oldx% = 1SI 
OldY% = 1SI 
Flag! = OSI 

SI 
CALL EmptyBuffersSI 
SI 

mousel: SI 
x% = PEEKW(WScreen& + 18)SI 
y% = PEEKW(WScreen& + 16)SI 
SI 

IF (x% <> Oldx%) OR (y%O01dY%) THENSI 



229 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



IF Flag! = 1 THEN f 

CALL Move& (RastPortS, Oldx%, 0) SI 

CALL Draw& (RastPortS, Oldx%, RasterHl%) SI 

CALL Move& (RastPortS, 0,OldY%)1 

CALL Draws (RastPort&,RasterWl%,OldY%) 31 

END IFSI 

Flag! = If 

CALL Move& (RastPortS ,x%, 0)SI 
CALL Draws (RastPortS , x%, RasterHl%) SI 
CALL Moves (RastPortS, 0,y%) SI 
CALL Draws (RastPortS ,RasterWl%, y%) SI 
Oldx% = x%SI 
OldY% - y%SI 
END IF SI 

IF MOUSE (0) = GOTO mouselSI 

CALL Moves (RastPortS, x%,0) SI 

CALL Draws (RastPortS, x%, RasterHl%) SI 

CALL Moves (RastPortS, 0,y%) SI 

CALL Draws (RastPortS , RasterWl%, y%) SI 

SI 
01dx% = -If 
01dY% - -1SI 
Flag! = OSI 
I 
WHILE MOUSE (0) <> OSI 
SI 

w% - PEEKW(WScreenS + 18) SI 

h% = PEEKW(WScreen& + 16)SI 

IF (w% <> Oldx%) OR (h% <> OldY%) THEN SI 

IF Flag! = 1 THEN CALL Box (RasLPorLS, x%, y%, Oldx%, OldY%) SI 
Flag! = 1SI 

IF (w% < x%+6) THEN w% = x%+6SI 
IF (h% < y% + 3) THEN h% = y%+3SI 
SI 

IF (w% > x%) AND (h% > y%) THENSI 

IF w%>RasterWl% THEN w% = RasterWl%SI 
IF h%>RasterHl% THEN h% = RasterHl%SI 
01dx% = w%SI 
OldY% = h%SI 
SI 
CALL Box (RastPortS, x%,y%,w%,h%) SI 
END IF SI 

END IFSI 
WEND SI 
SI 

IF Flag = 1 THEN CALL Box (RastPortS, x%, y%, w%, h%) SI 

SI 
CALL Printlt ("Section Ok ?", 130, True) SI 

Flag! - OSI 
Oldx% = -1SI 
01dY% = -If 

CALL DialogBox ("OK", 1, True, xla%, yla%, x2a%, y2a%, True) SI 



230 



Abacus 



Appendix B — The Tracer Program 



CALL EmptyBuffersf 

a$ = M,, SI 
WHILE (MOUSE (0) 
a$ = INKEY$SI 
WENDSI 



0) AND (a$ <> CHR$(13)) 



Mx% = PEEKW(WScreen&+18)1 
My% = PEEKW(WScreen&+16)SI 
SI 

TryAgain = Truest 

IF (Mx%>xla%) AND (Mx%<x2a%) AND (My%>yla%) AND (My%<y2a%) THEN TryAgain 
FalseSI 

IF a$ = CHR$(13) THEN TryAgain = FalseSI 
SI 

CALL Printlt ("Section Ok ?", 130, True) 1 
SI 
CALL DialogBox ("OK", 1, True, xla%, yla%, x2a%,y2a%, True) SI 
SI 

IF TryAgain - True THEN GOTO Repitition SI 
SI 

w% = w%-x%SI 
h% = h%-y% SI 
SI 

CALL SetDrMd& (RastPort&, 1) ' JAM 2 SI 
CALL SetDrMdS (NRastPort &, 1) SI 



IF Back! 

END SUBSI 



True THEN CALL ScroffSI 



NOOP: f 

Status$ = " Status: NOP"+CHR$ (0) SI 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 
RETURN SI 
'SI 
MakeMenu:SI 

Status$ = " Status: Building menu"+CHR$ (0) SI 

CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0) SI 

SI 

MENU 1,0,1, " Amiga"SI 

MENU 1,1,1," 3D-Cad-Info I "SI 



MENU 2, 


0,l,"File"SI 








MENU 


2,1,1, 


" Load 


L 


'SI 


MENU 


2,2,Start%, 


" Save 


S 


'SI 


MENU 


2,3,1, 


" Merge 


M 


'SI 


MENU 


2,4,1, 


" New 


N 


'1 


MENU 


2,5,0, 


H 




•si 






MENU 


2,6,1, 


" Load material 




'1 


MENU 
MENU 


2,7,0, 
2,8,Start%, 


n 




'SI 
'SI 


" Background 




MENU 


2,9,Start%, 


" Save screen 


P 


'SI 


MENU 


2,10,Start%, 


" Hardcopy 




'SI 


MENU 


2,11,0, 


it 




'1 






MENU 


2,12,Start%, 


" Color palette 


C 


'SI 


MENU 


2,13,0, 


n _ 




'SI 






MENU 


2,14,1, 


" Program end 


Q" 


SI 



MENU 3,0,l,"Editor"5 



231 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



MENU 3,1,1, 



Load Editor 



T1"SI 



MENU 4 
MENU 
MENU 



0, Start%, "Parameter"! 



4,l,Start%, 
4,2,Start%, 
MENU 4,3,Start%, 
MENU 4,4,Start%, 
MENU 4,5, 0, 
MENU 4, 6,Start%, 
MENU 4,7,start%, 



Projection point 
Main point 
a, _, c 
Distance 



Enlarge 
Number corner 



P"SI 
H"SI 
A"SI 
D"SI 

II CT 

V"SI 
E"SI 



MENU 5, 0,Start%, "Draw"SI 



MENU 5,l,Start%, 
MENU 5,2,Start%, 
MENU 5, 3,0, 
MENU 5,4,Start%, 
MENU 5,5,Start%, 
SI 

GOSUB NOOPSI 
CALL EmptyBuffersSI 
RETURNS 



Shadows F10"SI 
Initialization F9 "SI 



Wire model 
Clear screen 



< > m si 
c "si 



DeleteMenu:Sl 

MENU 1, 0,0, "Amiga"SI 
MENU 2,0,0,"File"SI 



MENU 

MENU 

MENU 

RETURNS 



3,0,0, "Editor"SI 
4, 0, 0, "Parameter" 
5, 0, 0, "Draw"SI 



Mess age Event : SI 

MTitle = MENU (0) "J 

MPoint - MENU (1) II 

SI 

IF MTitle <> THEN SI 

SI 

IF MTitle = 1 THENSI 

IF MPoint = 1 THEN GOSUB Inf 
GOTO MessageEndeSI 
END IFSI 



IF MTitle = 
IF MPoint 
IF MPoint 
IF MPoint 
IF MPoint 
' Mpoint 
IF MPoint 
' MPoint 
IF MPoint 
IF MPoint 
IF MPoint 
' MPoint 
IF MPoint 
' MPoint 
IF MPoint 
GOTO Mess 

END IFSI 

SI 

IF MTitle = 



2 THEN SI 

= 1 THEN GOSUB LoaderSI 
- 2 THEN GOSUB Saverl 
= 3 THEN GOSUB MergerSI 
= 4 THEN GOSUB ArraylnitSI 

= 5 : " "SI 

= 6 THEN GOSUB LoadMatSI 

■ 7 : " "SI 

= 8 THEN GOSUB Backgrounds! 
= 9 THEN GOSUB ScreenSaverSI 
= 10 THEN GOSUB HardCopySI 

= 11 : " "SI 

= 12 THEN GOSUB ColorPaletteSI 

= 13 : " "SI 

= 14 THEN GOSUB Quit SI 
lageEndeSI 



3 THEN SI 



232 



Abacus Appendix B — The Tracer Program 



IF MPcint = 1 THEN GOSUB LoadEditor! 
GOTO MessageEnde! 
END IF! 
! 
IF MTitle - 4 THEN! 

IF MPoint = 1 THEN GOSUB InputP! 
IF MPoint = 2 THEN GOSUB InputH! 
IF MPoint = 3 THEN GOSUB InputAngle! 
IF MPcint = 4 THEN GOSUB InputDPHS 

■ MPoint =5: " "S 

IF MPoint = 6 THEN GOSUB Enlargements 
IF MPoint - 7 THEN GOSUB HowManyCorners! 
GOTO MessageEndeS 
END IFS 
S 

IF MTitle = 5 THENS 

IF MPoint = 1 THEN GOSUB Shadows! 
IF MPoint = 2 THEN GOSUB InitParameters! 
IF MPoint = 4 THEN GOSUB DrawNew! 
IF MPoint = 5 THEN GOSUB ClearScreen! 
END IF! 
END IF! 

MessageEnde: ! 
RETURNS 
'! 
Key Event : SI 

Key$=INKEY$5 
IF Key$ <> "" THEN! 
LOCATE 1,1 SI 
SI 
IF Start% = 1 THENSI 

IF Key$ = " " THEN GOSUB DrawNewSI 
IF Key$ = "d" THEN GOSUB InputDPHS 
SI 

IF Key$ = "c" THEN GOSUB ColorPalette! 
SI 

"+» OR Key$ = "-" THENSI 



Key$ = 


"*" OR Key$ = 


"/" OR Key$ = 


IF Key$ 


= "+" THEN D 


= 10 SI 


IF Key$ 


= "-" THEN D 


=-10! 


IF Key$ 


= "*" THEN D 


= 1001 


IF Key$ 


= "/" THEN D 


= -100SI 



SI 



DPH = DPH + DSI 
GOSUB Initial^ 
Newone ! = True! 
WaitFlg! = TrueS 
GOSUB D raw New S 
END IFS 

IF Key$ = "v" THEN GOSUB Enlargements 

IF Key$ = "p" THEN GOSUB InputPS 

IF Key$ = "h" THEN GOSUB InputHS 

IF Key$ - "a" THEN GOSUB InputAngleS 

IF Key$ = "e" THEN GOSUB HowManyCornersS 

IF Key$ = "c" THEN GOSUB ClearScreenS 

IF Key$ = "s" THEN GOSUB Saver! 

IF Key$ - "b" THEN GOSUB ScreenSaver! 

IF Key$ = CHR$(137) THEN GOSUB InitParameters! 



2 33 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



IF Key$ = CHR$ (138) THEN GOSUB Shadows^ 
5 

IF (Key$ = CHR$ (28) ) OR (Key$ = CHR$ (29) ) OR (Key$ = CHR$ (30) ) OR (Key$ 
CHR$(31)) THEN5 

IF Key$ = CHR$ (28) THEN5 

Beta = Beta + Pi/155 
END IF 5 
IF Key$ - CHR$ (29) THEN5 

Beta = Beta - Pi/155 
END IF 5 

IF Key$ = CHR$ (30) THEN5 
Alpha = Alpha + Pi/151 
END IF 5 

IF Key$ = CHR$ (31) THEN5 
Alpha = Alpha - Pi /1 55 
END IF5 

GOSUB Initials 
Newone! = True5 
WaitFlg! = True5 
GOSUB DrawNew5 
END IF5 
5 

IF (Key$ = CHR$(18)) OR (Key$ = "R") THEN5 
IF Key$ = CHR$(18) THEN ' A R5 

Gamma = Gamma + Pi/155 
END IF 5 
IF Key$ = "R" THEN5 

Gamma = Gamma - Pi/155 
END IF5 

GOSUB Initialfl 
Newone! = True5 
WaitFlg! - True5 
GOSUB DrawNew5 
END IF 5 
END IF5 

IF Key$ = "m" THEN GOSUB Merger5 
IF Key$ = "n" THEN GOSUB Arraylnit 5 
IF Key$ = "1" THEN GOSUB Loader 5 

IF Key$ = "?" OR Key$ = CHR$ (139) THEN GOSUB Help5 
IF Key$ = "q" THEN Quit5 
IF Key$ = "i" THEN GOSUB Info5 
5 

IF Key$ = CHR$(1) THEN GOSUB LoadEditor5 
END IF 5 
RETURN5 



ColorPalette:5 

Status$ - " Status: Color change"+CHR$ (0) 5 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) 5 
5 

GOSUB DeleteMenu5 
5 

CALL SetRast& (RastPort&, 0) 5 

CALL Scron5 

CALL Printlt ("Which color to change ?", 100, True) c 

5 

NumCol = MaxColour%5 

IF NumCol = 64 THEN NumCol = 32 ' Halfbrite ?5 

Widthe = (RasterW%-40) /NumCol5 



234 



Abacus Appendix B — The Tracer Program 



LINE ((20 + 1) ,l)-(20+Widthe-l,RasterH%/10-l),l,b 1 
FOR i=l TO NumCol-11 

LINE ( (20+i*Widthe+l) , l)-( (20+ (i + 1) *Widthe) -1 , RasterH%/10-l ) , i,BFl 
IF MaxColour% = 64 THEN ' Halfbrite Colour output^ 

LINE ( (20+i*Widthe+l) , RasterH%/10) - ( (20+ (i + 1) *Widthe) -1 , RasterH%/5- 
l),i+32,BFl 

END IFSl 
NEXT1 
1 
LoopA:1 
CALL EmptyBuffersI 
1 

WHILE MOUSE (0) = Of 

WEND1 

1 

x = MOUSE (1)1 

y = MOUSE (2)1 

1 

IF (x < 20) OR (x > RasterW%-20) THEN 1 

GOTO LoopA:1 
END IF 1 
IF (y < 1) OR (y > RasterH%/10) THENl 

GOTO LoopA:Sl 
END IF1 
1 

Colr% = INT ( (x-20) /Widthe) ' which color was clickedl 
CALL Scroffl 

red=INT (Colour (Colr%+l, 1) *15. 5) 1 
green=INT (Colour (Colr%+l, 2) *15 .5) 1 
blue=INT (Colour (Colr%+l, 3)*15.5)1 
1 

LOCATE 10,11 

PRINT " red-component (0..15) : ";1 
CALL Formlnputlnt (red, 30 ! , ! , 15 ! ) 1 
1 

LOCATE 11,11 

PRINT " green-component (0..15) : ";1 
CALL Formlnputlnt (green, 30 ! , ! , 15 ! ) 1 
1 

LOCATE 12,11 

PRINT " blue-component (0..15) : ";1 
CALL Formlnputlnt (blue, 30 ! , ! , 15 ! ) 1 
1 

Colour (Colr%+l, 1) =red/151 
Colour (Colr%+l , 2) =green/151 
Colour (Colr% + l, 3) =blue/151 
1 

POKEW OSColour&+Colr%*8+2, red/15*10241 
POKEW OSColour&+Colr%*8+4, green/15*10241 
POKEW OSColour&+Colr%*8+6,blue/15*10241 
1 

IF MaxColour%=64 THEN "ExtraHalfBritel 

Colour (Colr%+33, 1) = (red\2) /151 
Colour (Colr%+33, 2) = (green\2) /151 
Colour (Colr% + 33, 3) = (blue\2) /151 
1 

POKEW OSColour&+Colr%*8+258, (red\2) /15*10241 
POKEW OSColour&+Colr%*8+260, (green\2) /15*10241 
POKEW OSColour&+Colr%*8+262, (blue\2) 715*10241 



235 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



END IFSI 
SI 

CALL SetRGB4& (Viewports, Colr%, CINT (red) , CINT (green) , CINT (blj-e) ) SI 
SI 

CALL DialogBox ("End" , 0, True, xla%, yla%, x2a%, y2a%, FaJ ;e}S T 
CALL DialogBox ("Next color" , 2, False, xlb%,ylb$, >'.' ; r: r ' , y2b%, Fal sis) SI 
SI 

CALL DoDialog (n%, 0, xla%, yla%, x2a%, y2a%, -1, -1 , -1, -l,xlb%, ylb%,x2b%, y2b%) c 
CLSSI 
SI 

IF n% = 2 THEN SI 

CALL ScronSI 

GOTO LoopASI 
END IFSI 

New one! = True SI 
Hg = FalseSI 
GOSUB MakeMenuSI 
RETURNSI 
'SI 
'SI 

ErrorHandli ng: SI 
NumErr - ERR SI 
SI 

Status$ - " Status: Next Big Error ! ! ! M -t-CHR$ (0) SI 
CALL SetWiodowTitles& (NWBaseS, SADD (Status$) , 0) Si 
SI 

GOSUB DeleteMenuSI 
SI 

Dialog$ = ""SI 
IF NumErr - 64 THEN ' Bad File Mode SI 

Dialog$ -■= "Bad file name ! ! ! "SI 
END IF SI 
SI 
IF NumErr - 57 THEN ' Device I/O ErrorSl 

Dialog$ = "Device I/O Error !! !"SI 
END IFSI 
SI 
IF NumErr = 68 THEN ' Device unabieSl 

Dialog$ - "Device not found" SI 
END IFSI 
SI 
IF NumErr = 61 THEN • Disk Full SI 

Dialog$ = "Diskette is tull !!!" Si 
END IFSI 
SI 
IF NumErr - 53 THEN ' File not foundS! 

Dialog$ = "File not found!!! "SI 
END IFSI 
SI 
IF NumErr = 70 THEN ' Permission deniedS! 

Dialog$ = "Permission denied '!! "SI 
END IFSI 
SI 
IF Dialog$ - "" THENSI 

Dialog$ = "Error Number ="+STR$ (NumErr) SI 
END IFSI 
SI 

CALL DialogBox (Dialog$, 1 , True, xla%, yla%, x2a%, y2a%, False) Si 
SI 
CALL DoDialog (n%, 1 , -1 , -1 ,-1,-1, xla%, y la%, x2a%, y2a%, -1 , -1 , -1 , -1 ) SI 



236 



Abacus Appendix B — The Tracer Program 



SI 

CLSSI 

GOSUB MakeMenuSI 
RESUME ok SI 
RETURNS 
'SI 
Quit: SI 

CALL ScroffSI 

Status$ = " Program end ?"+CHR$(0)SI 
CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 
SI 

GOSUB DeleteMenuSI 
SI 

CALL Prxntlt ("Do you really wi.sh to exit the program?", 100, False) 'ft 
SI 

CALL DialogBox ("No", 0, True, xla%, yla%, x2a%, y2a%, False) SI 
CALL DialogBox ("New start", 1, False, xlb%, ylb%,x2b%, y2b%, False) SI 
CALL DialogBox ("Yes", 2, False, xlc%, ylc%, x2c%, y2c%, False) SI 
SI 

CALL DoDialog(n%,0,xla%,yla%,x2a%,y2a%,xlb%,ylb%,x2b%,y2b%,xlc%,ylc%,x2c%,y2c%) 
SI 
SI 

CLSSI 

IF n% > THENSI 
GOSUB Close It SI 
IF n% = 1 THENSI 

RUN SI 
ELSESI 

ENDSI 
END IFSI 
END IFSI 

GOSUB MakeMenuSI 
RETURNSI 
■SI 

SUB Scroff STATICSI 
SHARED NWBase&,NWScreen&SI 

1 Display Screen off , User Screen onSI 
CALL ScreenToFront& (NWScreen&) SI 
WINDOW OUTPUT 1SI 
WINDOW 1SI 

CALL ActivateWindow& (NWBase&)SI 
END SUBSI 
'SI 

SUB Scron STATICSI 
SHARED WScreen&,WBase&SI 

' Display Screen on, User Screen offSI 
CALL ScreenToFront& (WScreen&)SI 
WINDOW OUTPUT 2 SI 
WINDOW 2SI 

CALL ActivateWindow& (WBaseS) SI 
END SUBSI 
'SI 

SUB GetString(old$,a$, z$, z, s,winlen) STATICSI 
TASK :Read a string while allowing the user to edit the strinqSI 
i.e. :cursor left/right, backspace and delete f unctions . SI 
In addition the string should be scrollable SI 
if the input is longer than the lineSI 
PARAMETER: =>old$ old value of string to be readSI 
a$ key pressedSI 
z$ legal charactersSI 



2 37 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



z lineal 
s columnSI 

winlen Length of input windpow^I 
<=old$ of specified string^ 
IF winlen=l THEN 'if only 1 character entered? => no <Return> neededSl 
old$=a$fl 
WHILE INSTR(z$ / old$)=01 

CALL GetKey (old$,z,s)f 
WENDf 

LOCATE z,sfl 
PRINT old$fl 
ELSEf 

i=l 'display current string position^ 

Position=l 'display the actual screen position f 

WHILE a$XCHR$ (13) ^1 

IF INSTR(z$,a$)><0 THEN 'legal character?^ 

old$=LEFT$ (old$,i-l)+a$+RIGHT$(old$,LEN(old$)-i+l) fl 

i=i+lfl 

Position=Position+l ( I 

IF Position>winlen THEN<I 

Position=winlenf 
END IF 1 
ELSE f 

IF a$ = CHR$(30) AND i<=LEN(old$) THEN 'Cursor right ?SI 
i=i+lf 

Posit ion=Position+lf 
IF Position>winlen THEN^I 

Position=winlenSI 
END IF f 
ELSEf 

IF a$ = CHR$(31) AND i>l THEN 'Cursor left?fl 
i=i-HI 

Position=Position-15 
IF Position=0 THENSl 

Positional! 
END IF SI 
ELSE! 

IF a$ = CHR$(127) AND i<=LEN(old$) THEN 'delete ?! 

old$=LEFT$ (old$, i-1) +RIGHT$ (old$, LEN (old$) -i) ! 
ELSE! 

IF a$=CHR$(8) AND i>l THEN 'Backspace ?! 
i=i-l! 

Position=Position-l! 
IF Position=0 THEN! 

Position=l! 
END IF! 

old$=LEFT$ (old$, i-1) +RIGHT$ (old$, LEN (old$) -i) 5 
END IF! 
END IF! 
END IF! 
END IF! 
END IF! 
LOCATE z,s! 

PRINT MID$(old$ + " ", i-Position+1, winlen) 'String outputs 
CALL GetKey (a$, z, s+Position-1) 'get next key 
WEND ! 
END IF! 
IF ixPosition THEN! 

CALL PutString (old$, z, s, winlen) ! 
END IF ! 



238 



Abacus Appendix B — The Tracer Program 



END SUB! 
! 

SUB GetReal (i !, a$, z, s, winlen, unt !, ob! ) STATIC! 
TASK :Read a real valued 
PARAMETER :=>i! old valued 

a$ pressed key! 
z line5 
s column! 

winlen length of input line! 
unt! lower limit SI 
ob! upper limit! 
<=i ! given value! 
CALL conrealstr (i ! , j$) ! 
loopl: ! 
i$=j$! 

CALL Get St ring (i$, a$," 12345 67890-.",z,s, winlen)! 
j$=i$! 

CALL constrreal (i$,i ! ) ! 
IF i$= ,,M OR i!<unt! OR i!>ob! THEN! 
a$=" "! 
BEEP! 

GOTO loopl! 
END IF! 
END SUB! 
'! 

SUB Getlnt (i! ,a$, z, s, winlen, unt! ,ob! ) STATIC! 
TASK :Read a Integer value! 
PARAMETER: =>i ! old value! 

a$ key pressed! 
z line! 
s column! 

winlen Length of input line! 
unt! upper limit! 
ob! lower limit! 
<=i ! given value! 
CALL conrealstr (i!, j$)! 
loop3: ! 
i$=j$! 

CALL GetString (i$, a$, "1234567890-", z, s, winlen) ! 
j$=i$! 

CALL constrreal (i$,i!)! 
IF i$="" OR i!<unt! OR i!>ob! THEN! 
a$=" "! 
BEEP! 

GOTO loop3! 
END IF! 
END SUB! 
'! 

SUB GetKey (a$,z,s) STATIC! 
'TASK :Read a Character ! 
' PARAMETER :=>z line! 
1 s column! 

1 <=a$ key pressed! 

CALL SetCursor (z,s) ! 
a$=""! 

WHILE a$=""! 
a$=INKEY$! 
WEND! 

CALL SetCursor (z, s)! 
END SUB! 



239 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



•SI 

SUB SetCursor(z, s) STATICSI 

'TASK :set the cursor to the given positional 
' PARAMETER :=>z linefl 
1 s column^ 

rp&=WINDOW(8)SI 
Cw%=PEEKW(rp&+60)SI 
Ch%=PEEKW(rp&+58)SI 
CALL SetDrMd& (rp&,2)<5 

LINE (s*Cw%-Cw%,z*Ch%-Ch%)-(s*Cw%,z*Ch%) ,3,BFSI 
CALL SetDrMdS (rp&,l)SI 
END SUB SI 
'SI 

SUB PutString(s$, z, s, winlen) STATICSI 
TASK : Output a string of the specified lengthSI 
PARAMETER :=>s$ the string*! 
z lineSI 
s column SI 

winlen lenghtof the output stringSI 
LOCATE z,s 'delete given rangeSI 

PRINT SPACE$ (winlen) SI 

LOCATE z,s 'output the stringSI 

PRINT MID$ (s$,l,winlen)SI 
END SUBSI 
SI 
SUB PutReal (i! , z, s, winlen) STATICSI 
TASK :Output a real value of the specified lengthSI 
PARAMETER: =>i! the real valueSI 
z lineSI 
s column SI 

winlen length of the output windowSI 
CALL conrealstr (i!,s$)SI 
CALL PutString(s$, z, s, winlen) SI 
END SUBSI 
' SI 

SUB conrealstr (i ! , i$) STATICSI 

'TASK : convert one real value to a stringSI 
' rounding off value to three decimal placesSI 

' PARAMETER: =>i! the Real valueSI 
' <=i$ the stringSI 

i$=STR$(i!)SI 

j!=FIX(1000!*i!+.5*SGN(i!) )/1000! ' roundSI 
i$=STR$(j!)SI 
IF ABS(j!)>0 AND ABS ( j ! ) <1 THEN 'Insert if 0<j!<l SI 

i$=MID$(i$,l,l)+"0 ,, +MID$(i$,2,LEN(i$) ) SI 
END IFSI 
IF j!>=0 THEN 'falls 0<=j! truncate first placeSI 

i$=RIGHT$ (i$,LEN(i$) -1)1 
END IFSI 
END SUBSI 
'SI 

SUB constrreal (i$,i! ) STATICSI 
'TASK : convert string to real valueSI 
' PARAMETER: =>i$ the stringSI 

<=i! the real valueSI 
' i$ If conversion error i$ = ""SI 

i!-VAL(i$)SI 
IF i!>=0 THENSI 

IF i!>0 AND i!<l THENSI 

i$=" "+RIGHT$ (i$,LEN (i$) -1) 'Insert space and remove OS 



240 



Abacus Appendix B — The Tracer Program 



ELSE SI 

i$=" "+i$ 'insert spaceSI 
END IFSI 

END IFfl 

j!=i!-FIX(i!*1000!)/1000! 'round f 

IF i$XSTR$(i!) OR j!><0 THEN 'error ?SI 
i$=""SI 

END IF f 
END SUBSI 
'SI 

SUB Formlnput (i,winlen,unt ! , ob! ) STATICS! 
'Enter indivudal real valuesSI 

' i => number variables to be real (old value displayed) SI 

' winlen,unt ! , ob ! => see above. SI 

z=CSRLINl 

s=POS(0)SI 

a$ = " "SI 

CALL PutReal (i, z, s, winlen) SI 

CALL GetReal (i, a$, z, s, winlen, unt !, ob! ) f 
END SUBfl 
'SI 

SUB Formlnputlnt (i, winlen, unt !, ob! ) STATICSI 
'Enter an indivudal integer valued 

1 i => number variavles to be read (old value displayed) SI 

1 winlen, unt !, ob ! => see above. SI 

z=CSRLINSI 

s=-POS(0)SI 

a$ = ■• "SI 

CALL PutReal (i, z, s, winlen) SI 

CALL Getlnt (i , a$, z, s, winlen, unt !, ob! ) SI 
END SUBSI 
'SI 

SUB FormlnputString (s$, winlen) STATICSI 
' String read (e.g. Filename) SI 

a$ = " "SI 

s = POS(O) SI 

z = CSRLINSI 

CALL PutSt ring (s$, z, s, winlen) SI 

CALL GetString 
(s$,a$, "abcdefghi jklmnopqrstuvwxyzdv | _ABCDEFGHI JKLMNOPQRSTUVWXYZDVM234567890 . - 
_: /", z, s, winlen) SI 
END SUBSI 
•SI 
Directory : SI 

' Directory read, or change driveSI 

Status$ = " Status: Directory"+CHR$ (0) SI 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 

SI 

GOSUB DeleteMenuSI 

a$ = "Active Directory: "+ActDrive$SI 

CALL Printlt (a$, 50, False) f 

CHDIR ActDrive$SI 

SI 

RepeatD:SI 

CALL DialogBox ("Files", 0, False, xla%,yla%, x2a%, y2a%, False) SI 
CALL DialogBox ("Continue", 1 , True, xlb%, ylb%, x2b%, y2b%, False) SI 
CALL DialogBox ("Chdir" , 2, False, xlc%, ylc%, x2c%, y2c% , False) SI 

SI 

CALL DoDialog(n%, 1, xla% , yla%, x2a%, y2a%, xlb%, ylb%, x2b%, y2b%, xlc%, ylc%, x2c%, y2c%) 
SI 



241 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



si 



CLSSI 

IF n% = THENi 

FILESSI 

GOSUB Paused 

CLSSI 

GOTO RepeatD^I 
END IFSI 
IF n% = 2 THENSI 

a$ = "Active Directory: "+ActDrive$SI 

CALL Printlt (a$, 50, False) SI 
SI 

LOCATE 10,1 SI 

PRINT " New Directory: ";SI 

CALL FormlnputString (ActDrive$, 30 ! ) SI 



CHDIR ActDrive$SI 
SI 
CLSSI 

GOTO RepeatDSI 
END IF Si 
CLSSI 
RETURN SI 

"End of SYSTEM. ASCSI 



242 



Abacus Appendix B — The Tracer Program 



The WIREMODEL-DRAW.ASC module 



WIREMODEL-Draw . ASCSI 



* Wire model *SI 



SUB Projection (Px%, Py%, x, y, z) STATICSI 

SHARED Sina, Sinb, Sine, Cosa, Cosb, Cose, DPH, Hx, Hy, HzSI 

' 3D coordinates (x,y,z) to 2D (Px%,Py%) = ScreenSI 
SI 

xl=(x-Hx) *Cosa+ (y-Hy) *Sina ' Z-Axis rotationSl 

yl= (y-Hy) *Cosa- (x-Hx) *SinaSI 

x2=xl*Cosb+ (z-Hz) *Sinb ' Y-Axis rotationSl 

z2=(z-Hz) *Cosb-xl*SinbSI 

y3=yl*Cosc+z2*Sinc ' X-Axis rotationSl 

z3=z2*Cosc-yl*SincSI 
SI 

IF DPHOx3 THENSI 

Px%=FN Xscale( (y3*DPH) / (DPH-x2) ) -4 ' Intersecting point with projection point 
SI 

Py%=FN Yscale( (z3*DPH) /(DPH-x2) ) -2 • scaling^ 

ELSESI 

Px% = FN Xscale(O) -4 ' Subtraction of 4 and 2 based on drawingSI 
Py% = FN Yscale(O) -2 ' in a GIMMEZEROZERO-Window (BASIC-Window) SI 

END IFSI 
END SUB SI 
'SI 
'SI 
DrawPlane:SI 

CALL 
Projection (Xp%,Yp%,K(n%, 2, 0)+K(n%,l,0),K(n%, 2, 1)+K(n%, 1,1) ,K (n%, 2, 2) +K (n%, 1, 2) ) SI 

CALL Moves (RastPort S, Xp%, Yp%) SI 

CALL Projection (Xp%,Yp%,K(n%, 1,0) ,K (n%, 1, 1) , K (n%, 1 , 2) ) SI 

CALL Draws (RastPortS, Xp%, Yp%) SI 

CALL 
Projection(Xp%,Yp%,K(n%,3,0)+K(n%,l,0),K(n%,3,l)+K(n%,l, 1) , K (n%, 3, 2) +K (n%, 1 , 2) ) SI 

CALL Draws (RastPortS, Xp%, Yp%) SI 
RETURNSI 
'SI 
DrawTriangle: SI 

CALL Projection(xl%,yl%,K(n%,l,0) ,K (n%, 1 , 1) , K (n%, 1 , 2) ) SI 

CALL Moves (RastPort S, xl%, yl%) SI 

CALL 
Projection(Xp%,Yp%,K(n%,2,0)+K(n%,l,0) , K (n%,2, 1) +K (n%, 1, 1) , K (n%, 2, 2) +K (n%, 1 , 2) ) SI 

CALL Draws (Rast Ports, Xp%,Yp%) SI 

CALL 
Projection(Xp%,Yp%,K(n%,3,0)+K(n%,l,0),K(n%,3,l)+K(n%, 1 , 1) , K (n%, 3, 2) +K (n%, 1 , 2 ) ) SI 

CALL Draws (RastPort S, Xp%, Yp%) SI 

CALL Draws (RastPort S, xl%, yl%) SI 
RETURNSI 
'SI 



243 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



DrawRec tangle : SI 

CALL Projection (xl%,yl%,K(n%, 1,0) ,K (n%, 1, 1) ,K(n%, 1, 2) ) SI 
CALL Move& (RastPort S, xl%,yl%) SI 
CALL 
Projection (Xp%,Yp%,K(n%, 2, 0) +K (n%, 1, 0) , K (n%, 2, 1) +K (n%, 1, 1) , K (n%, 2, 2) +K (n%, 1, 2) ) SI 
CALL Draw& (RastPortS, Xp%,Yp%) SI 
Dx=K(n%,2,0)+K(n%, 3, 0) +K (n%, 1, 0) SI 
Dy=K (n% , 2 , 1 ) +K (n%, 3 , 1 ) +K (n%, 1 , 1 ) 1 
Dz=K(n%,2,2)+K(n%,3,2)+K(n%,l,2)SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz ) 1 
CALL Draws (RastPortS, Xp%,Yp%) SI 
CALL 
Projection(Xp%,Yp%,K(n%,3,0)+K(n%,l,0),K(n%,3,l)+K(n%,l,l) , K (n%, 3, 2) +K (n%, 1, 2) ) SI 
CALL Draws (RastPort S, Xp%,Yp%) SI 
CALL Draws (RastPort S, xl%,yl%) SI 
RETURNS 
'SI 
DrawCircle:SI 

CALL 
Projection(Xp%,Yp%,K(n%,l,0)+K(n%,2,0),K(n%,l,l)+K(n%,2,l) , K (n%, 1, 2) +K (n%, 2, 2) ) SI 
' SIN(0) = and COS(0) = 1 goto K(n%,3, ..), and K(n%,2,..) takes overSl 
CALL Moves (RastPort S, Xp%, Yp%) SI 
w=Pm2 /Number Segment sSI 
D=wSI 
Repeatl:SI 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w)fl 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)SI 
Dz=K (n%, 1 , 2) +K (n%, 2, 2) *COS (w) +K (n%, 3, 2) *SIN (w) SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Draws (RastPort S,Xp%,Yp%) SI 
w = w+DSI 
IF (w<=Pm2+D/2) THEN GOTO Repeatl:SI 
RETURN SI 
'SI 
DrawCircleSector : SI 

CALL Projection (xl%, yl%, K (n%, 1,0) ,K(n%,l,l) , K (n%, 1 , 2) ) SI 
w=K(n%,5,0)SI 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w)SI 
Dy=K (n%, 1 , 1 ) +K (n%, 2, 1 ) *COS (w) +K (n%, 3, 1 ) *SIN (w) SI 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Moves (RastPortS, xl%,yl%) SI 
CALL Draws (RastPortS, Xp%,Yp%) SI 
D^Pm2/NumberSegmentsSI 
WHILE w<K(n%,5,l)SI 
w = w+DSI 
IF w>K(n%,5,l) THENSI 

w=K(n%,5,l)SI 
END IFSI 

Dx=K(n%,l,0)+K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w)SI 
Dy=K (n%, 1 , 1 ) +K (n%, 2, 1) *COS (w) +K (n%, 3, 1) *SIN (w) SI 
Dz=K (n%, 1 , 2) +K (n%, 2, 2) *COS (w) +K (n%, 3, 2) *SIN (w) SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Draws (RastPortS, Xp%,Yp%) SI 
WENDSI 

CALL Draws (RastPortS, xl%,yl%)SI 
RE TURN SI 
'SI 

DrawCircleRingrSI 
w-K(n%,5,0)SI 



244 



Abacus Appendix B — The Tracer Program 



Dx=K(n%,l,0)+(K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w))*K(n%,4,0)5 

Dy=K (n%, 1, 1) + (K (n%, 2, 1) *COS (w) +K (n%, 3, 1) *SIN (w) ) *K (n%, 4,0)1 

Dz=K(n%,l,2)MK(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w))*K(n%,4,0)5 

CALL Projection (Xua%, Yua%, Dx, Dy, Dz) 5 

Dx=K{n%,l,0)MK(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w))*K(n%,4,l)5 

Dy=K(n%,l,l)^K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w))*K(n%,4,l)5 

Dz=K(n%,l,2)+(K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w))*K(n%,4,l)5 

CALL Projection (Xoa%, Yoa%, Dx, Dy, Dz) 5 

CALL Moves (RastPortS, Xua%, Yua%) 5 

CALL Draws (RastPortS, Xoa%,Yoa%) 5 

D=Pm2 /Number Segment s5 

WHILE w<K(n%,5,l)f 

w = w+D5 

IF w>K(n%,5,l) THEN? 
w=K(n%,5,l)5 

END IF? 

Dx=K(n%,l,0)+(K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w) )*K(n%,4,0)? 

Dy=K (n%, 1, 1) + (K (n%, 2,1) *COS (w) +K (n%, 3, 1) *SIN (w) ) *K (n%, 4 , 0) ? 

Dz=K(n% / l / 2)+(K{n% / 2 / 2)*COS(w)+K(n%,3 / 2)*SIN(w))*K(n%,4 / 0)1 

CALL Projection (Xu%, Yu%, Dx, Dy, Dz) ? 

Dx=K(n%,l,0)+(K(n%,2,0)*COS(w)+K(n%,3,0)*SIN(w) )*K(n%,4,l)? 

Dy=K(n%,l,l) + (K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w) ) *K (n%, 4 , 1 ) ? 

Dz=K(n%,l,2)+(K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w) )*K(n%,4,l)? 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) ? 

CALL Moves (RastPortS, Xua%, Yua%)? 

CALL Draws (RastPortS, Xu%, Yu%) 5 

CALL Moves (RastPortS, Xp%, Yp%) 5 

CALL Draws (RastPort6,Xoa%, Yoa%) 5 

Xua%=Xu%? 

Yua%=Yu%? 

Xoa%=Xp%? 

Yoa%=Yp%? 
WEND? 

CALL Moves (RastPortS, Xua%, Yua%) 5 
CALL Draws (RastPortS, Xoa%, Yoa%) ? 
RETURN? 
'? 
DrawSphere:? 

D=Pm2/NumberSegments? 

FOR wl=-Pd2+D TO Pd2-D/2 STEP D? 

Dx=K(n%,l,0)? 

Dy=K (n%, 1 , 1) +K (n%, 2 , 0) *COS (wl) ? 

Dz=K (n%, 1, 2) +K (n%, 2, 0) *SIN (wl ) ? 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) 1 

CALL Moves (RastPortS,Xp%, Yp%) 5 

FOR w2=D TO Pm2+D/2 STEP D? 

Dx=K (n%, 1 , 0) +K (n%, 2, 0) *SIN (w2) *COS (wl) \ 
Dy=K (n%, 1, 1) +K (n%, 2, 0) *COS (w2) *COS (wl) \ 
Dz=K (n%, 1 , 2) +K (n%, 2, 0) *SIN (wl) ? 
CALL Projection (Xp%, Yp%,Dx, Dy, Dz) \ 
CALL Draws (RastPortS, Xp%,Yp%)? 

NEXT w2? 
NEXT wl? 
FOR wl=-Pd2+D TO Pd2-D/2 STEP D? 

Dy=K(n%,l,l)? 

Dz=K(n%,l,2)+K(n%,2,0)*COS(wl)? 

Dx=K(n%,l,0)+K(n%,2,0)*SIN(wl)? 

CALL Projection (Xp%,Yp%,Dx, Dy,Dz) 5 

CALL Moves (RastPort S, Xp%, Yp%) 5 

FOR w2=D TO Pm2+D/2 STEP D? 



245 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



Dy=K (n%, 1, 1) +K (n%, 2, 0) *SIN <w2) *COS (wl) 1 
Dz=K (n%, 1, 2) +K (n%, 2, 0) *COS (w2) *COS (wl) 1 
Dx=K (n%, 1, 0) +K (n%, 2, 0) *SIN (wl) 1 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) 1 
CALL Draws (RastPortS , Xp%, Yp%) 1 
NEXT w21 
NEXT wll 
RETURN! 
'1 
DrawCyl indent 

Dx=K(n%,l,0)+K(n%,2,0)1 

Dy=K(n%,l,l)+K(n%,2,l)1 

Dz=K(n%,l,2)+K(n%,2,2)1 

CALL Projection (Xua%, Yua%, Dx, Dy, Dz) 1 

Dx=K(n%,l,0)+K(n%,2,0)+K(n%, 4,0)1 

Dy=K(n%,l,l)+K(n%,2,l)+K(n%, 4,1)1 

Dz=K(n%,l,2)+K(n%,2,2)+K(n%, 4,2)1 

CALL Projection (Xoa%, Yoa%, Dx, Dy, Dz) 1 

D-Pm2 /Number Segment si 

FOR w=D TO Pm2+D/2 STEP D1 

Dx=K(n%,l,0)+K(n%,2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) 1 
Dy=K(n%,l,l) +K(n%,2,l) *COS (w) +K (n%, 3, 1) *SIN(w)1 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)1 
CALL Projection (Xu%, Yu%, Dx, Dy, Dz) 1 

Dx=K (n%, 1, 0; +K (n%, 2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) +K (n%, 4,0)1 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)+K(n%,4,l)1 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)+K(n%,4,2)1 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) 1 
CALL Moves (RastPortS , Xua%, Yua%) 1 
CALL Draws (RastPort S, Xu%, Yu%) 1 
CALL Draws (RastPort S, Xp%, Yp%) 1 
CALL Draws (RastPort S , Xoa%, Yoa%) 1 
Xua%-Xu%1 
Yua%=Yu%1 
Xoa%=Xp%1 
Yoa%=Yp%1 
NEXT wl 
RET URN 1 
'1 

DrawCylinderSegm: 1 
w=K(n%,5, 0) 1 

Dx=K(n%,l,0)+K(n%,2,0)*CGS(w)+K(n%,3,0)*SIN(w)1 
Dy=K(n%,l, 1 ) + K (n%, 2, 1 ) *COS (w) +K (n%, 3, 1 ) *SIN (w) 1 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)1 
CALL Projection (Xua%, Yua%, Dx, Dy, Dz) 1 

Dx=K (n%, 1, 0) tK (n%, 2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) +K (n%, 4, 0) 1 
Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)+K(n%,4,l)1 
Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)+K(n%,4,2)1 
CALL Projection (Xoa%, Yoa%, Dx, Dy,Dz) 1 
CALL Moves (RastPort S, Xua%, Yua%) 1 
CALL Draws (RastPort S, Xoa%, Yoa%) 1 
D=Pm2/NumberSegment si 
WHILE w<K(n%,5,l)1 
w = w+DI 

IF w>K(n >,5,1) TKEN1 
w=K(n%,5,l)1 



END IF1 












Dx=K(n%,l, 


,0)+K(n%, 


,2, 


. 0)*COS(w)+K(n%, 


,3, 


.0)*SIN(w)1 


Dy=K(n%,l, 


,1)+K(n%, 


,2, 


1) *C0S(w)+K(n%, 


,3, 


,l)*SIN(w)1 


Dz=K(n%,l, 


,2)+K(n%, 


2, 


2) *C0S(w)+K(n%, 


,3, 


. 2)*SIN(w)1 



246 



Abacus Appendix B — The Tracer Program 



CALL Projection (Xu%, Yu%, Dx, Dy, Dz) SI 

Dx=K(n%, 1, 0) +K (n%, 2, 0) *COS (w) +K (n%, 3, 0) *SIN (w) +K (n%, 4, 0) SI 

Dy=K(n%,l,l)+K(n%,2,l)*COS(w)+K(n%,3,l)*SIN(w)+K(n%,4,l)SI 

Dz=K(n%,l,2)+K(n%,2,2)*COS(w)+K(n%,3,2)*SIN(w)+K(n%,4,2)SI 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 

CALL Move& (RastPortS , Xua%, Yua%) SI 

CALL Draws (RastPortS, Xu%, Yu%) SI 

CALL Draws (RastPortS, Xp%, Yp%) SI 

CALL Draw& (RastPortS , Xoa%, Yoa%) SI 

Xua%=Xu%SI 

Yua%=Yu%SI 

Xoa%=Xp%SI 

Yoa%=Yp%SI 
WENDf 
RETURNS 
'SI 
DrawCone:f 

CALL 
Projection (xl%, yl%, K (n%, 1, 0) +K (n%, 4 , 0) , K (n%, 1, 1) +K (n%, 4,1) ,K (n%, 1, 2) +K (n%, 4, 2) ) SI 

CALL 
Projection(Xp%,Yp%,K(n%,l,0)+K(n%,2,0),K(n%,l,l)+K(n%,2,l) ,K (n%, 1, 2) +K(n%, 2, 2) ) SI 
CALL Move& (RastPortS, Xp%, Yp%) SI 
D=Pm2 /Numbe rSegment sSI 
FOR w=D TO Pm2+D/2 STEP DSI 

Dx=K(n%, 1, 0) +K (n%, 2, 0) *COS (w) +K(n%, 3, 0) *SIN (w) St 

Dy=K(n%, 1, 1) +K (n%, 2, 1) *COS (w) +K (n%, 3, i) *SIN (w) SI 

Dz=K (n%, 1 , 2) +K (n%, 2, 2) *COS (w) +K (n%, 3, 2) *SIN (w) SI 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) 1 

CALL Draws (RastPortS, Xp%,Yp%) SI 

CALL Moves (RastPortS, xl%, yl%) 1 

CALL Draws (RastPortS, Xp%, Yp%) SI 
NEXT wSI 
RETURNS 
'SI 
DrawEllipsoidrSI 

D=Pm2 /Number Segments SI 

FOR wl=-Pd2+D TO Pd2-D/2 STEP DSI 

Dx=K (n%, 1, 0) +K (n%, 2, 0) *COS (wl) +K (n%, 4, 0) *SIN (wl) SI 

Dy=K(n%,l,l)+K(n%,2,l)*COS(wl)+K(n%,4,l)*SIN(wl)SI 

Dz=K(n%,l,2)-fK(n%,2,2)*COS(wl)+K(n%,4,2)*SIN(wl)SI 

CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 

CALL Moves (RastPortS, Xp%, Yp%) SI 

FOR w2=D TO Pm2+D/2 STEP DSI 

Dx=K(n%, 1, 0) +K(n%, 2, 0) *COS (wl) *COS (w2) +K (n%, 3, 0) *COS (wl) *SIN (w2) +K (n%, 4, 0) *SIN (wi) SI 
Dy=K (n%, 1, 1) +K (n%, 2, 1) *COS (wl) *COS (w2) +K (n%, 3, 1) *COS (wl) *SIN (w2) +K (n%, 4,1) *SIN (wl ) SI 

Dz=K (n%, 1, 2) +K (n%, 2, 2) *COS (wl) *COS (w2) +K (n%, 3, 2) *COS (wl) *SIN (w2) +K (n%, 4,2) *SIN (wl ) SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Draws (RastPortS, Xp%,Yp%) SI 
NEXT w2SI 
NEXT wlSI 
FOR wl=-Pd2+D TO Pd2-D/2 STEP DSI 

Dx=K(n%,l,0)+K(n%,2,0)*COS(wl)+K(n%,3,0)*SIN(wl)SI 
Dy=K(n%, 1, 1) +K (n%, 2,1) *COS (wl) +K (n%, 3, 1) *SIN (wl) SI 
Dz=K (n%, 1, 2) +K (n%, 2,2) *COS (wl) +K (n%, 3, 2) *SIN (wl) SI 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) SI 
CALL Moves (RastPortS, Xp%,Yp%) SI 



247 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



FOR w2=D TO Pm2+D/2 STEP Df 
Dx=K (n%, 1, 0) +K (n%, 2, 0) *COS (wl) *COS (w2) +K (n%, 4, 0) *COS (wl) *SIN (w2) +K <n%, 3, 0) *SIN (wl) < 

Dy=K(n%,l,l)+K(n%,2,l)*COS(wl)*COS(w2)+K(n%, 4, 1) *COS (wl) *SIN (w2) +K (n%, 3, 1) *SIN (wl) c 

Dz=K(n%,l,2)+K(n%,2,2)*COS(wl)*COS(w2)+K(n%,4, 2) *COS (wl) *SIN (w2) +K (n%, 3, 2) *SIN (wl) < 
CALL Projection (Xp%, Yp%, Dx, Dy, Dz) f 
CALL Draws (RastPort&,Xp%, Yp%) f 
NEXT w2f 
NEXT wlf 
RETURNf 



DrawAll:f 

* Draw routine for calling each figured 
FOR n%=l TO NumberKf 
IF K(n%,0,0)=0 THENf 

GOSUB DrawPlanef 
END IFf 
IF K(n%,0,0)=l THENf 

GOSUB DrawTrianglef 
END IFf 
IF K(n%,0,0)=2 THENf 

GOSUB DrawRectanglef 
END IFf 
IF K(n%,0,0)=3 THENf 

GOSUB DrawCirclef 
END IFf 
IF K(n%,0,0)=4 THENf 

GOSUB DrawCircleSectorf 
END IFf 
IF K(n%,0,0)=5 THENf 

GOSUB DrawCircieRingf 
END IFf 
IF K(n%, 0,0) =10 THENf 

GOSUB DrawSpheref 
END IFf 

IF K(n%,0,0)=20 THENf 
GOSUB DrawCylinderf 
END IFf 
IF K(n%,0,0)=21 THENf 

GOSUB DrawCylinderSegmf 
END IFf 
IF K(n%,0,0)=22 THENf 

GOSUB DrawConef 
END IFf 
IF K(n%,0,0)=24 THENf 

GOSUB DrawEllipsoidf 
END IFf 
NEXT n%f 
RETURNf 
'f 
DrawNew:f 

IF (Hg = False) AND (Newone! = True) THEN ' no Background! 

CALL SetRast& (RastPort&, 0) ' but new drawing! 

END IF ' => clear screenf 

f 
CALL Scron f 



248 



Abacus 



Appendix B — The Tracer Program 



IF (Newone! = True) OR (Hg = True) THEN 

GOSUB DeleteMenuSI 

RetRastS = RastPort& 

RastPort& = WINDOW (8) 

CALL SetAPen& (RastPortS, 1) 

GOSUB DrawAll 

RastPortS = RetRast&SI 

BEEP SI 
END IFSI 
SI 



Background and New drawingSI 



IF WaitFlg! = True THEN 

GOSUB Pause 

CALL ScroffSI 
END IFSI 



' reserve RastPort SI 
' In Window-RastPort 
1 the new ScreensSI 
draw (because of Clipping) 



(GIMMEZERO Window! ) c 



wait for mouse or key pressSl 



IF (Newone! = True) OR (Hg = True) THENSI 

Newone! = False ' Redraw picture SI 

Hg = False ' and "paint over"SI 

GOSUB MakeMenu ' background SI 

END IFSI 
RETURNSI 
'SI 
HowManyCorners : SI 

Status$ = " Status: Draw angles at n-corners"+CHR$ (0) SI 
CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 



SI 



GOSUB DeleteMenuSI 
SI 

LOCATE 1 , 1 SI 

PRINT " How many corners : ";SI 
CALL Formlnputlnt (NumberSegments, 30 !, ! , 200 ! ) SI 
Newone! = True SI 
CLSSI 

GOSUB MakeMenuSI 
RETURNSI 
'SI 
Enlargement : SI 

Status$ - " Status: Enlarge screen segment "+CHR$ (0) SI 
CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 
SI 

GOSUB DeleteMenuSI 
SI 

CALL DialogBox ("Proportional", 0, True, xla%, yla%, x2a%, y2a%, False) SI 
CALL DialogBox ("Distort" , 2, False, xlb%, ylb%, x2b%, y2b%, False) SI 
SI 

CALL DoDialog(n%,0,xla%,yla%,x2a%,y2a%,xlb%,ylb%,x2b%,y2b%, -1,-1,-1, -1 ) SI 
CLSSI 
Tl 

IF n%=0 THEN SI 
LOCATE 10,1 SI 

PRINT " Enlargement Factor: ";SI 
a=lSI 
CALL Formlnput (a, 30 ! , . 1 , 100 ! ) SI 

SI 
CLS SI 

Picturewidth=a*FactorXSI 
Pictureheight=a*FactorYfl 
Picturex-RasterW2%/PicturewidthSI 
Picturey=--RasterH2%/PictureheightSI 



249 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



ELSEf 

WaitFlg! = Falsest 

GOSUB DrawNewfl 

CALL Rubberbox (Sx%, Sy%, Widthe%, Heighte%, False) < 

Picturewidth=RasterW%/Widthe% * FactorX^l 

Pictureheight=RasterH%/Heighte% * FactorYSI 

Picturex= (RasterW2%-Sx%) /FactorXfl 

Picturey= (RasterH2%-Sy%) /FactorY f 
END IFfl 

Newone! = Truefl 
WaitFlg! = Truefl 
GOSUB DrawNewf 
RETURNS 
'END of Wire-model. ascl 



250 



Abacus Appendix B — The Tracer Program 



The WIREMODEL-INPUT.ASC module 



WI REMODEL- 1 NP UT . ASC 

* Input-Routine *f 
************************cr 

II 
Initial :5 

WHILE Alpha<0^1 

Alpha - Alpha + Vm2f 
WENDf 
WHILE Beta<0fl 

Beta = Beta + Pm2<II 
WENDfl 
WHILE Gamma<0SI 

Gamma = Gamma + Pm2f 
WENDfl 
WHILE Alpha>Pm2fl 

Alpha = Alpha - Pm2f 
WENDfl 
WHILE Beta>Pm2f 

Beta = Beta - Pm2f 
WEND<5 
WHILE Gamma>Pm21 

Gamma = Gamma - Pm2SI 
WEND1 

Sina=SIN (Alpha) <fl 
Cosa=COS (Alpha) 1 
Sinb=SIN(Beta) f 
Cosb=COS(Beta) <fl 
Sinc=SIN (Gamma) f 
Cosc=COS (Gamma) f 

Px=Hx+DPH*Cosa*Cosb * Projection point based on the 

Py=Hy+DPH*Sina*Cosb ' main point and the spacings^I 

Pz=Hz+DPH*Sinb ' DPH and Alpha, Beta and Gamma*! 
RETURN f 

InitialP:<fl 

D1=SQR ( (Px-Hx) "2+ (Py-Hy) "2) f 

DPH=SQR ( (Px-Hx) "2+ (Py-Hy) "2+ (Pz-Hz) "2) f 

IF D1=0 THENSI 

Sina-Of 

Cosa=lSI 
ELSE^l 

Sina= (Py-Hy) /Dll 

Cosa= (Px-Hx) /Dlfl 
END IFfl 
<K 

IF DPH=0 THENfl 

Sinb=0f 

Cosb=lfl 
ELSEf 

Sinb= (Pz-Hz) /DPHf 



251 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



Cosb=Di/DPHSI 

END IFSI 

SI 

Sinc=0 ' Z-Axis angle not SI 

Cosc=l ' solely determined hereSI 

SI 

IF Cosa=0 THEN SI 
Alpha=Pd2SI 

ELSSSI 

Alpha=ATN (Sina/Cosa) ' compute cosinemand sinel 

END IF ' angleSI 

SI 

IF Cosa<0 THEN SI 
Alpha - Alpha* Pi SI 

END IFSI 
SI 

IF Cosb=-0 THEN SI 
Beta=Pd2Sl 

ELSESI 

Beta-ATN (Sinb/Cosb) SI 

END IF SI 
SI 

IF Cosb<C THEN SI 

Beta - Beta + Pi SI 

END IF SI 
SI 

Gamma=0SI 
RE TURN SI 
'SI 
InputPrSI 

Status$ = " Status: Projection point "+CHR$ (0) SI 

CALL Se tW i ndowT i 1 1 e s & (NWBa se & , SADD ( S t a t u s $ ) , ) SI 
SI 

GOSUB DeleteMenuSI 
SI 

LOCATE 10, I Si 

PRINT " Projection point: "SI 

SI 

LOCATE 12,11 

PRINT " Px = ";SI 

CALL Formlnput (Px, 30 ! , -1E+14, 1E+14) SI 
SI 

LOCATE 1 3 , 1 SI 

PRINT " Py - ";SI 

CALL Formlnput (Py, 30 ! , -1E+14, 1E+14 ) SI 
SI 

LOCATE 14,1 SI 

PRINT " Pz - ";SI 

CALL Formlnput (Pz, 30 ! , -1E + 1 4, 1E+14 ) SI 

SI 

GOSUB InitialPSI 

Newone ! = True SI 

CLSSI 

GOSUB MakeMenu SI 
RETURNS! 
'SI 
! SI 
InputH:SI 

Status? - " Status: Main point "+CHR$ (0) 1 

CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0) 1 



252 



Abacus Appendix B — The Tracer Program 



GOSUB DeleteMenuSl 
SI 

LOCATE 10,1 SI 

PRINT " Main point: "SI 
SI 

LOCATE 12, 1^1 

PRINT " Hx = ";SI 

CALL Formlnput (Hx, 30 ! , -1E+14, 1E+14) SI 
SI 

LOCATE 13, If 

PRINT " Hy = ";SI 

CALL Formlnput (Hy, 30 ! , -1E+14, 1E+14 ) SI 
SI 

LOCATE 14,15 

PRINT " Hz - ";SI 

CALL Formlnput (Hz, 30 ! , -1E+14, 1E+14 ) SI 
1 

GOSUB InitialSI 

Newone! = TrueSI 

CLSSI 

GOSUB MakeMenuSI 
RETURNS 
'SI 
InputDPHiSI 

Status$ = " Status: Spacing"+CHR$ (0) SI 

CALL SetWindowTitles& (NWBaseS, SADD (Status$) , 0) SI 

SI 

GOSUB DeleteMenuSl 

SI 

LOCATE 10,1 SI 

PRINT " Spacing of projection surface = ";SI 

CALL Formlnput (DPH, 30 ! , -1E+14, 1E+14 ) SI 
SI 

GOSUB InitialSI 

Newone! = True SI 

CLSSI 

GOSUB MakeMenuSI 
RE TURN SI 
■1 
InputAnglerSI 

Status$ = " Status: Enter angle of rotation"+CHR$ (0) c 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 

SI 

GOSUB DeleteMenuSl 
SI 

a=FN Deg (Alpha). SI 

b=FN Deg (Beta) SI 

c=FN Deg (Gamma) SI 

SI 

LOCATE 10,1 SI 

PRINT " Angle of rotation (a,_,c): "SI 
1 

LOCATE 12,1 SI 

PRINT " Alpha (Z-Axis) = ";SI 

CALL Formlnput (a, 30 ! , ! , 360 ! ) SI 
SI 

LOCATE 13,1 SI 

PRINT " Beta (Y~Axis) - ";SI 

CALL Formlnput (b, 30 ! , ! , 360 ! ) SI 



253 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



LOCATE 14,11 

PRINT " Gamma (X-Axis) = ", 
CALL Formlnput (c, 30 ! , ! , 360 ! ) c 
1 

Alpha=FN Rad(a)1 
Beta=FN Rad (b) 5 
Gamma=FN Rad(c) f 

GOSUB Initials 

New one! = True<fl 

CLSfl 

GOSUB MakeMenufl 
RETURNS 
'End of wi remodel -Input. asc^L 



254 



Abacus Appendix B — The Tracer Program 



The SHADOW-INIT.ASC module 



SHADOW-INIT.ASCSI 

* Shadows initialization *SI 

***•**•*• *********************** ****** qj 
1 

InitParameters : SI 

Status$ = " Status: Parameter initia!ization"+CHR$ (0) SI 
CALL SetWindowTitlesS (NWBase&, SADD (Status$) , 0) f 
SI 
GOSUB DeleteMenuSI 
1 

CALL Print It ("Shadow window?" , 130, False) SI 
CALL DialogBox ("All", 0, True, xla%, yla%,x2a%,y2a%, False) SI 
CALL DialogBox ("Section", 1, False, xlb%,ylb%, x2b%, y2b%, False) SI 
CALL DialogBox ("YA - YE", 2, False, xlc%, ylc%, x2c%, y2c%, False) SI 

SI 
CALL DoDialog(n%,C^xla%,yla%,x2a%,y2a%,xlb%,ylb%,x2b%,y2c%,xlc%,ylc%,x2c%,y2c%) ( 
CLSSI 
SI 

IF n% = THEN SI 
XStart% = OSI 
YStart% - OSI 
XEnd% = RasterWl%SI 
Yend% - RasterHl%SI 
END IFSi 
SI 

IF n% = I THENSI 

CALL Rubberbox (Sx%, Sy%, Widthe%, Heighte%, True) SI 

SI 
XStart%=Sx%Sl 
YStart%=Sy%SI 
XEnd%-Sx%+Widthe%SI 
Yend%=Sy%+Heighte%SI 
END IFSI 
SI 

IF n% - 2 THENSI 
CALL ScronSI 
SI 

CALL SetDrMdfi (RastPortS, 2) SI 
SI 

XStart% = OSI 

XEnd% = RasterWl%Sl 

SI 

CALL EmptyBuffersSl 

01dY% = -1SI 

Flag = OSI 

SI 

WHILE (MOUSE (0) = 0)SI 

y% - PEEKW(NWScreen& + 16)SI 
IF y% <> OldY% THENSI 

CALL Moves (RastPortS , 0, y%) SI 

CALL Draws (RastPort& , RasterWl%, y%) SI 

IF Flag <> THENSI 



255 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



CALL Move& (RastPortS, 0,OldY%)! 
CALL Draws (RastPort&,RasterWl%, OldY%) ! 
END IF! 
Flag = 1! 
OldY% = y%! 
END IF! 
WEND! 
! 
YStart% = y%! 

OldY% = -1! 

Flag = 0! 

! 

WHILE (MOUSE (0) <> 0)1 

y% = PEEKW(NWScreenS+16)! 
IF y% <> OldY% THEN! 

CALL Move& (RastPortS , 0,y%) ! 

CALL Draws (RastPortS , RasterWl%, y%) ! 

IF Flag <> THEN! 

CALL Moves (RastPortS, 0,OldY%)! 
CALL Draws (RastPortS, RasterWI%, 01dY%) ! 
END IF! 
Flag - 1! 
01dY% = y%! 
END IF! 
WEND! 

Yend% - y%! 

! 

IF YStart% > Yend% THEN SWAP YStart%, Yend%! 

CALL Moves (RastPortS , 0,YStart%) ! 

CALL Draws (RastPortS , RasterWl%, YStart%) ! 

CALL Moves (RastPortS, 0,Yend%)! 

CALL Draws (RastPortS , RasterWl%, Yend%) ! 

! 

CALL SetDrMdS (RastPortS,!) ! 

CALL Scroff! 
END IF! 
! 

LOCATE 2,1! 

PRINT " Xstart = ";XStart%; " , Xend = ";XEnd%! 
PRINT " Ystart = " ; YStart%; ", Yend = ";Yend%! 

LOCATE 6,1! 

PRINT " Position of light source :"! 

! 

LOCATE 8, 1! 

PRINT " Qx = ";! 

CALL Formlnput (Qx, 30 ! , -1E+1 4, 1E+14 ) ! 

LOCATE 9,1! 

PRINT " Qy = ";! 

CALL Formlnput (Qy, 30 ! , -1E+14, 1E+14 ) ! 

LOCATE 10,1! 

PRINT " Qz = ";! 

CALL Formlnput (Qz, 30 ! , -1E+14, 1E+14) ! 



256 



Abacus Appendix B — The Tracer Program 



LOCATE 13,1 SI 

PRINT " Color of light source"*! 

SI 

LOCATE 15,11 

PRINT " red-intensity (0..1) = ";SI 

CALL Formlnput (Qh . r , 30 ! , ! , 1 ! ) SI 

LOCATE 16,1 SI 

PRINT " green-intensity (0..1) = ";SI 

CALL Formlnput (Qh. g, 30 ! , ! , 1 ! ) SI 

LOCATE 17, 1SI 

PRINT " blue-intensity (0..1) - ";SI 

CALL Formlnput (Qh. b, 30 ! , ! , 1 ! ) SI 

LOCATE 19,1 SI 

PRINT " Pixel width : ";SI 

a = BoxW%SI 

CALL Formlnputlnt (a, 30 ! , 1 ! , CSNG (RasterWl%) ) SI 

BoxW% = aSI 

LOCATE 20,1 SI 

PRINT " pixel height : ";SI 

a = BoxH%SI 

CALL Formlnputlnt (a, 30 ! , 1 ! , CSNG (RasterHl%) ) SI 

BoxH% = aSI 

CALL Printlt ("Which pattern?" , 130, False) SI 

CALL DialogBox ("Standard", 0, True, xla%,yla%, x2a%, y2a%, False) SI 
CALL Di alogBox( "Extended", 2, False, xlb%, ylb%,x2b%, y2b%, False) SI 
SI 
CALL EmptyBuffersSI 

CALL DoDialog (PatternArt%, 0, xla%,yla%, x2a%,y2a%, -1,-1,-1, - 
PatternArt% = PatternArt% AND If 
SI 

CLSSI 

GOSUB MakeMenuSI 
RE TURN SI 



SUB Transform (Xt, Yt,Zt,x,y, z,n%) STATICSI 
SHARED K() , Help () SI 

1 => (xt,yt,zt) = transformation vector base k(n%)SI 
SI 

Xt=FN Det (x-K(n%,l,0) ,K(n%,3,0) ,K (n%, 4, 0) , y-K (n%, 1, 1) ,K(n%,3,l) , K (n%, 4, 1 ) , z- 
K(n%,l,2) ,K(n%,3,2),K(n%,4,2))/Help(n%,0)SI 

Yt=FN Det (K(n%,2,0),x-K(n%,l,0),K(n%,4,0) ,K (n%, 2, 1) ,y- 
K(n%,l,l) ,K(n%,4,l),K(n%,2,2) , z-K (n%, 1, 2) , K(n%, 4, 2) ) /Help (n%, 0) SI 

Zt=FN Det(K(n%,2,0),K(n%,3,0),x-K(n%,l,0) ,K (n%, 2, 1) ,K (n%, 3, 1) , y- 
K(n%,l,l) ,K(n%,2,2) ,K(n%,3,2) , z-K (n%, 1 , 2) ) /Help (n%, 0) SI 
END SUBSI 
'SI 
InitShadows:SI 

* Write as much as was computed previously into the help arraySI 

ERASE HelpSI 

DIM Help(NumberK,21)SI 

SI 

FOR n%=l TO NumberKSI 
IF K(n%,0,0)< = 9 THENSI 

' Triangle, Rectangle or Circle => Help(n,0..2) = normal vector on surfaced 
1 Help (n, 3.. 5) = 2*2-Determinante for x,y,zSI 



257 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



Nx=K(n%,2,l)*K(n%,3,2)-K(n%,2,2)*K(n%,3,l)fl 
Ny=K(n%,2,2)*K(n%,3,0)-K(n%,2,0)*K(n%,3,2)SI 
Nz=K(n%,2,0)*K(n%,3,l)-K(n%,2,l)*K(n%,3,0)SI 

IF FN CosiriAngle(Nx,Ny,Nz,Px-K(n%,l,0),Py-K(n%,l,l) ,Pz-K(n%,l,2) )<0 THENSI 
1 => Normal vector points to Projection points 
Nx=-NxSI 
Ny=-NySI 
Nz=-NzSI 
END IFfl 

N1=SQR (Nx*Nx+Ny*Ny+Nz*Nz) SI 
Nx = Nx/NlSI 
Ny - Ny/NlSI 
Nz = Nz/Nlf 
SI 

Help(n%,0)=NxSl 
Help(n%,l)=Nyfl 
Help(n%,2)=NzSI 

Help(n%,3)=K(n%,2,l)*K(n%,3,2)-K(n%,3,l) *K(n%,2, 2) SI 
Help(n%,4)=K(n%,2,0)*K(n%,3,2)-K(n%,3,0)*K(n%,2,2)SI 
Help(n%,5)=K(n%,2,0)*K(n%,3,l)-K(n%,3,0)*K(n%,2,l)Sl 
END IFSI 
IF K(n%,0,0)>=20 THENSI 

1 Help (n, 0) =Names determinant, l-6=for Normal vector cylinder, 7=length 
(n,4,x)SI 

1 10-12=transform Projection pointf 
' 13-21=2*2-Determinantes for P/R-TransformationSI 
Help(n%,0)=FN 
Det (K(n%,2,0) , K (n%, 3, 0) , K (n%, 4, 0) ,K (n%, 2, 1) , K (n%, 3, 1) ,K(n%,4,l) ,K (n%, 2, 2) , K (n%, 3, 2 
),K(n%,4,2))SI 

IF Help(n%,0)=0 THENSI 

a$="The basis of object "+STR$ (n%) + " is no basis"SI 

CALL Printlt(a$, 130, False) f 

CALL DialogBox ("Pitch", 1, True, xla%,yla%, x2a%, y2a%, False) SI 



-1, 



CALL DoDialog (n%, 1 

GOSUB Closeltf 

RUN SI 
END IFSI 

a=K(n%,2,0) A 2+K (n%, 2, 1) A 2+K (n%, 2, 2) A 2SI 
b=K(n%,3,0) A 2+K(n%,3,l) A 2+K(n%,3,2) A 2SI 
IF K(n%,0,0)>=24 THENSI 

c=K(n%,4,0) A 2+K(n%,4,l) A 2+K(n%,4,2) A 2SI 



I,xla%,yla%,x2a%,y2a%, -1,-1, -1,-1) SI 



Help (n%, 1 ) =b*c*K (n%,2, 0) SI 






Help(n%,2)=b*c*K(n%,2,l)SI 






Help (n%, 3) =b*c*K (n%, 2, 2) 1 






Help (n%, 4 ) =a*c*K (n%, 3, 0) SI 






Help(n%,5)=a*c*K(n%,3,l)SI 






Help (n%, 6) =a*c*K (n%, 3, 2) 1 






Help (n%, 7) =a*b*K (n%, 4, 0) SI 






Help (n%, 8) =a*b*K (n%, 4, 1) SI 






Help (n%, 9) =a*b*K (n%, 4, 2) SI 






ELSESI 






Help(n%,l)=a*K(n%,3,0)SI 






Help(n%,2)=a*K(n%,3,l)SI 






Help(n%,3)=a*K(n%,3,2)SI 






Help(n%,4)=b*K(n%,2,0)SI 






Help(n%,5)=b*K(n%,2,l)S[ 






Help(n%,6)=b*K(n%,2,2)SI 






Help (n%, 7) =SQR (K (n%, 4, 0) A 2+K (n%, 4, 1) A 2+K (n%, < 


4,2) A 2)SI 


END IFSI 







258 



Abacus 



Appendix B — The Tracer Program 



CALL Transform (Xt, Yt, Zt,Px,Py,Pz, n%)<H 
Help(n%,10)=Xtf 
Help(n%,ll)=Ytf 
Help(n%,12)=ZtSI 

Help(n%,13) = (K(n%,3,l)*K(n%,4,2)-K(n%, 
Help(n%,14) = (K(n%,3,0)*K(n%,4,2)-K(n%, 
Help(n%,15) = (K(n%,3,0)*K(n%,4,l)-K(n%, 
Help(n%,16) = (-K(n%,2,l)*K(n%,4,2)+K(n : 
Help(n%,17) = (-K(n%,2,0)*K(n%,4,2)+K(n' 
Help(n%,18) = (-K(n%,2,0)*K(n%,4,l)+K(n ; 
Help(n%,19) = (K(n%,2,l)*K(n%,3,2)-K(n% 
Help(n%,20) = (K(n%,2,0) *K (n%, 3, 2) -K (n% 
Help (n%, 21) = (K (n%, 2, 0) *K (n%, 3, 1) -K (n% 
END IFSI 
NEXT n%SI 
RETURNS 



,4,l)*K(n%,3,2) ) /Help (n%, 0)5 
4,0)*K(n%,3,2) ) /Help (n%, 0) SI 
.4,0) *K(n%,3,l) )/Help(n%,0)SI 
5,4,1) *K(n%,2,2) )/Help(n%, 0) SI 
5,4,0) *K(n%,2,2) ) /Help (n%, 0) SI 
5,4,0) *K(n%, 2,1) ) /Help(n%,0)SI 
3,1) *K(n%,2,2) )/Help(n%,0)SI 
,3,0) *K(n%,2,2) ) /Help (n%, 0) SI 
, 3,0) *K(n%,2, 1) ) /Help (n%, 0)11 



SUB Transformmm(x,y, z) STATIC^ 

SHARED Sina,Sinb, Sine, Cosa,Cosb, Cose, RasterWl%,RasterH13 
SHARED DPH,Hx,Hy,Hz,Xt,Yt,Zt! 
' => xt,yt,zt for minmaxSI 



xl= (x-Hx) *Cosa+ (y-Hy) *Sina 
yl= (y-Hy) *Cosa- (x-Hx) *SinaS 
Xt=xl*Cosb+ (z-Hz) *Sinb 
z2= (z-Hz) *Cosb-xl*SinbSI 
y3=yl*Cosc+z2*Sinc 
z3=z2*Cosc-yl*SincSI 



Rotation Z-AxisSI 



Rotation Y-AxisS 



Rotation X-AxisSI 



IF DPHOZt THENSI 

Yt =FN Xscale( (y3*DPH) /(DPH-Xt) ) 

Zt =FN Yscale ((z3*DPH)/ (DPH-Xt) ) 
ELSEf 

Yt = FN Xscale(O) SI 

Zt = FN Yscale (0) SI 
END IFSI 



division point with projection planeSI 
scaledSI 



IF Yt<0 THENSI 

Yt=0SI 
END IFSI 
IF Yt>RasterWl% THENSI 

Yt=RasterWl%SI 
END IFSI 
IF Zt<0 THENSI 

Zt=0SI 
END IFSI 
IF Zt>RasterHl% THENSI 

Zt=RasterHl%SI 
END IFSI 
END SUBSI 



SUB MinMaxtest (n%,x,y,z) STATICSI 

SHARED DPH,minmax% () , RasterWl%, RasterHl%, Xt, Yt, Zt,XMin%SI 

SHARED YMin%,XMax%,YMax%SI 

' if point preceding projection point => minmax% (n%, 0) = 
IF minmax% (n%, 0) >=0 THENSI 
CALL Transformmm(x,y,z) SI 
IF Xt>=DPH THENSI 
minmax% (n%,0)=-lSI 



= > no screen limit SI 



259 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



minmax% (n%, 1) =-15 
minmax% (n%, 2) =RasterWl%<]I 
minmax% (n%, 3) =RasterHl%SI 
XMin%=05 
XMax%=RasterWl%fl 
YMin%=0SI 
YMax%=RasterHl%SI 
ELSESI 

IF Yt<minmax% (n%, 0) THENSI 

minmax% (n%, 0)=Ytf 
END IF5 
IF Yt>minmax% (n%,2) THENf 

minmax% (n%, 2)=Ytf 
END IFSI 
IF Zt<minmax% (n%,l) THENSI 

minmax% (n%, l)=Ztfl 
END IFfl 
IF Zt>minmax% (n%, 3) THENSI 

minmax% (n%,3)=ZtSI 
END IFSI 
IF Yt<XMin% THENSI 

XMin%=Yt<fl 
END IF1 
IF Yt>XMax% THENSI 

XMax%=Ytfl 
END IFSI 
IF Zt<YMin% THENSl 

YMin%=Zt<H 
END IFfl 
IF Zt>YMax% THENSI 

YMax%=ZtSI 
END IF1 
END IFSI 
END IFfl 
END SuBSl 
■SI 
InitMinMax:^ 

1 Compute screen section allocated for indivudal objects*]] 

ERASE minmax%SI 
DIM minmax% (NumberK, 3) SI 
SI 

XMin%=RasterWl%SI 
XMax%=0SI 

YMin%=RasterHl%SI 
YMax%=0f 
SI 

FOR n%=l TO NumberKSI 

minmax% (n%, 0) =RasterWl%SI 
minmax% (n%, 1 ) =RasterHl%SI 
minmax%(n%,2)=0SI 
minmax% (n%,3)=0SI 
SI 

IF K(n%,0,0)=0 THENSI 
minmax% (n%,0)=0SI 
minmax%(n%,l)=0SI 
minmax% (n%, 2) =RasterWl%SI 
minmax% (n%, 3) =RasterHl%1 
XMin%=0SI 
XMax%=RasterWl%SI 



260 



Abacus Appendix B — The Tracer Program 



YMin%=0SI 
YMax%=RasterHl%SI 
END IFSI 
SI 

IF K(n%,0,0)=l THENSI 

CALL MinMaxtest (n%, K (n%, 1, 0) , K (n%, 1, 1) , K (n%, 1 , 2) ) f 
CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0), K(n%, 1,1) +K(n%, 2,1) , K (n%, 1, 2) +K (n%, 2, 2) ) SI 

CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 3,0), K(n%, 1,1) +K(n%, 3,1) , K (n%, 1, 2) +K (n%, 3, 2) ) SI 

END IFSI 
SI 

IF K(n%,0,0)=2 THENSI 

CALL MinMaxtest (n%, K (n%, 1 , 0) , K (n%, 1 , 1 ) , K (n%, 1 , 2) ) SI 
CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0), K(n%, 1,1) +K(n%, 2,1) ,K (n%, 1, 2) +K (n%, 2, 2) ) SI 

CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 3,0), K(n%, 1,1) +K(n%, 3,1) ,K (n%, 1, 2) +K (n%, 3, 2) ) SI 

CALL 
MinMaxtest (n%,K(n%, 1,0) +K (n%, 2,0) +K(n%, 3,0), K(n%, 1,1) +K(n%, 2,1) +K(n%, 3,1) ,K(n%, 1,2) 
+K(n%,2,2)+K(n%,3,2) ) SI 

END IFSI 
SI 

IF K(n%,0,0)>=3 AND K(n%,0,0)<=5 THENSI 

CALL MinMaxtest ( n% , K (n% , 1 , ) -K (n% , 2 , ) -K ( n% , 3 , ) , K ( n% , 1 , 1 ) -K ( n% , 2 , 1 ) - 
K(n%,3,l),K(n%,l,2)-K(n%,2,2)-K(n%,3,2))SI 

CALL MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0) -K(n%, 3,0) , K (n%, 1, 1) +K (n%, 2, 1) - 
K(n%,3,l) ,K(n%,l,2)+K(n%,2,2)-K(n%,3,2) ) SI 

CALL MinMaxtest (n%, K(n%, 1, 0) -K(n%, 2, 0) +K (n%, 3, 0) , K (n%, 1, 1) - 
K(n%,2,l)+K(n%,3,l) , K (n%, 1, 2) -K (n%, 2, 2) +K (n%, 3, 2) ) SI 

CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0) +K(n%, 3,0), K(n%, 1,1) +K(n%, 2,1) +K(n%, 3,1) ,K(n%, 1,2) 
+K(n%,2,2)+K(n%,3,2))SI 

END IFSI 
SI 

IF K(n%,0,0)=10 THENSI 

CALL MinMaxtest (n%,K(n%, 1,0) -K(n%, 2,0), K(n%, 1,1) -K(n%, 2,0) ,K(n%,l,2)- 
K(n%,2,0))Sl 

CALL MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0), K(n%, 1,1) -K(n%, 2,0), K(n%, 1,2) - 
K(n%,2,0))SI 

CALL MinMaxtest (n%,K(n%, 1,0) -K(n%, 2,0), K(n%, 1,1) +K(n%, 2,0) ,K(n%,l,2)- 
K(n%,2,0))SI 

CALL MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0), K(n%, 1,1) +K(n%, 2,0) ,K(n%,l,2)- 
K(n%,2,0))SI 

CALL MinMaxtest (n%, K (n%, 1, 0) -K (n%, 2, 0) , K (n%, 1 , 1 ) - 
K(n%,2,0) ,K(n%,l,2)+K(n%,2,0) ) SI 

CALL MinMaxtest (n%, K (n%, 1, 0) +K (n%, 2, 0) , K (n%, 1, 1) - 
K(n%,2,0) ,K(n%,l,2)+K(n%,2,0) ) SI 

CALL MinMaxtest (n%,K(n%, 1,0) - 
K(n%,2,0) ,K(n%,l,l)+K(n%,2,0) , K(n%, 1, 2) +K(n%, 2, 0) ) SI 

CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0) , K (n%, 1, 1) +K (n%, 2, 0) ,K (n%, 1, 2) +K (n%, 2, 0) ) SI 

END IFSI 
SI 

IF (K(n%,0,0)=20) OR (K (n%, 0, 0) =21) OR (K (n%, 0, 0) =24) THENSI 
IF K(n%,0,.0)=20 THENSI 
Xh%=K(n%,l,0)SI 
Yh%=K(n%, 1,1)1 
Zh%=K(n%,l,2)SI 
ELSESI 



261 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



Xh%=K(n%,l,0)-K(n%,4,0)fl 
Yh%=K(n%,l,l)-K(n%,4,l)fl 
Zh%=K(n%,l,2)-K(n%,4,2)fl 
END IFSI 

CALL MinMaxtest (n%, Xh%-K (n%, 2, 0)-K(n%,3,0) ,Yh%-K(n%,2, 1) -K(n%,3,l) , Zh%- 
K(n%,2,2)-K(n%,3,2) )fl 

CALL MinMaxtest (n%,Xh%+K(n%,2, 0) -K(n%, 3, 0) , Yh%+K (n%, 2, 1) - 
K(n%,3,l) ,Zh%+K(n%,2,2)-K(n%,3,2) )\ 

CALL MinMaxtest (n%, Xh%-K (n%, 2, 0) +K (n%, 3, 0) , Yh%-K (n%, 2, 1) +K (n%, 3,1), Zh%- 
K(n%,2,2)+K(n%,3,2))f 

CALL 
MinMaxtest (n%, Xh%+K (n%, 2, 0)+K(n%, 3, 0),Yh%+K(n%, 2, 1)+K(n%, 3,1) , Zh%+K (n%, 2, 2) +K (n%, 3, 
2))fl 

Xh%=K(n%,l,0)+K(n%, 4,0)1 
Yh%=K(n%,l,l)+K(n%,4,M 
Zh%=K(n%, 1,2) +K(n%, 4,2)1 

CALL MinMaxtest (n%, Xh%-K (n%, 2, 0) -K (n%, 3, 0) , Yh%-K (n%, 2, 1) -K (n%, 3, 1) , Zh%- 
K(n%,2,2)-K(n%,3,2) )1 

CALL MinMaxtest (n%, Xh%+K (n%, 2, 0) -K (n%, 3, 0) , Yh%+K (n%, 2, 1) - 
K(n%,3,l) , Zh%+K(n%,2,2) -K (n%, 3, 2) ) 1 

CALL MinMaxtest (n%,Xh%-K (n%, 2, 0) +K (n%, 3, 0) , Yh%-K (n%, 2, 1) +K (n%, 3, 1) , Zh%- 
K(n%,2,2)+K(n%,3,2))1 

CALL 
MinMaxtest (n%, Xh%+K (n%, 2, 0) +K (n%, 3, 0) , Yh%+K (n%, 2, 1 ) +K (n%, 3, 1) , Zh%+K (n%, 2, 2) +K (n%, 3 
,2))1 

END IF1 
1 

IF K(n%,0,0)=22 THEN1 

CALL MinMaxtest (n%, K (n%, 1, 0) -K (n%, 2, 0) -K (n%, 3, 0) , K (n%, 1, 1) -K (n%, 2, 1) - 
K(n%,3,l),K(n%,l,2)-K(n%,2,2)-K(n%,3,2))1 

CALL MinMaxtest (n%,K(n%, 1, 0) +K (n%, 2, 0) -K (n%, 3, 0) , K (n%, 1, 1) +K (n%, 2, 1 ) - 
K(n%,3,l),K(n%,l,2)+K(n%,2,2)-K(n%,3,2))1 

CALL MinMaxtest (n%, K (n%, 1, 0) -K (n%, 2, 0) +K (n%, 3, 0) ,K(n%,l,l)- 
K(n%,2,l)+K(n%, 3,l),K(n%,l,2)-K(n%,2,2)+K(n%,3,2))f 

CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 2,0) +K(n%, 3,0), K(n%, 1,1) +K(n%, 2,1) +K(n%, 3,1) ,K(n%,l,2) 
+K(n%,2,2)+K(n%,3,2) )1 

CALL 
MinMaxtest (n%,K(n%, 1,0) +K(n%, 4,0) , K (n%, 1, 1 ) +K (n%, 4, 1) , K (n%, 1, 2) +K (n%, 4,2) )1 
END IFl 
NEXT n%1 
1 

IF XMin%>XStart% THEN1 

XStart%=XMin%1 
END IFl 
IF XMax%<XEnd% THEN1 

XEnd%=XMax%1 
END IFl 
IF YMin%>YStart% THEN1 

YStart%=YMin%1 
END IFl 
IF YMax%<Yend% THEN1 

Yend%=YMax%1 
END IFl 
RETURNS 



SUB NormalAngle (Pw,Wi) STATIC^ 
SHARED Pi,Pm21 

' => Picture Wi from [ -PI , +PI 



262 



Abacus Appendix B — The Tracer Program 



WHILE Wi>PiSI 
Wi=Wi-Pm2SI 

WENDSI 

WHILE Wi<=-PiSI 
Wi=Wi+Pm2SI 

WENDSI 

Pw=WiSI 
END SUB1 
'SI 
SUB Deltasum3(Pw,wl,w2,w3) STATICSI 

' => if light source in triangle: w=2*pi, else w=0SI 

CALL NormalAngle (Dl,w2-wl) SI 

CALL NormalAngle (D2,w3-w2) SI 

CALL NormalAngle (D3,wl-w3) SI 

Pw=Dl+D2+D3SI 
END SUBSI 
'SI 
SUB Deltasum4 (Pw,wl,w2,w3,w4) STATICSI 

' => if light source in triangle: w=2*pi, else w=0SI 

CALL NormalAngle (Dl,w2-wl) SI 

CALL NormalAngle (D2, w3-w2) 1 

CALL NormalAngle (D3,w4-w3)SI 

CALL NormalAngle (D4,wl-w4)1 

Pw=Dl+D2+D3+D4fl 
END SUBSI 
'SI 

SUB GETxyzlq(Px,Py,Pz,n%,a%,b%,c%) STATICSI 
SHARED K()SI 

1 => Compute XYZ-coordinates from factors a,b, cSI 

Px=K(n%, 1, 0) +a%*K (n%, 2, 0) +b%*K(n%, 3, 0) +c%*K (n%, 4, 0) \ 

Py=K (n%, 1 , 1 ) +a%*K (n%, 2, 1) +b%*K (n%, 3, 1) +c%*K (n%, 4, 1 ) f 

Pz=K(n%,l,2)+a%*K(n%,2,2)+b%*K(n%,3,2)+c%*K(n%,4,2)SI 
END SUBSI 
'SI 

SUB GETxyzlqk(Px,Py,Pz,n%,a%,b%,c%) STATICSI 
SHARED K()SI 

1 => Compute XYZ-coordinates for Sphere from factors a,b,cSI 

Px=K (n%, 1, 0) +a%*K (n%, 2, 0) SI 

Py=K(n%,l,l)+b%*K(n%,2,0)SI 

Pz=K(n%,l,2)+c%*K(n%,2,0)SI 
END SUBSI 
'SI 

SUB Disttest (x,y,z) STATICS! 
SHARED Qx,Qy,Qz,MinDistSI 

1 => Compute distance (x,y, z) froml ight sourceSI 
D=SQR( (x-Qx) A 2+(y-Qy) A 2+ (z-Qz) A 2) ' Pythagoream theoremSI 

IF MinDist<0 THENSl 
MinDist=DSI 

ELSESI 

IF D<MinDist THEN MinDist=Df 

END IFSI 
END SUBSI 
'SI 

SUB Arctan(Pw,xl,yl,x2,y2) STATICSI 
SHARED Pi,Pd2SI 

' Determine pw=arctan ( (yl-y2) / (xl-x2) ) SI 

IF xl=x2 THENSI 

Hw=SGN(yl-y2)*Pd2SI 

ELSESI 

Hw=ATN ( (yl-y2) / (xl-x2) ) SI 



263 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



IF xl<x2 THEN? 
IF Hw>=0 THEN? 

Hw=Hw-Pi? 
ELSE? 

Hw=Hw+Pi? 
END IF? 
END IF? 
END IF? 
Pw=Hw? 
END SUB? 
'? 

SUB Calcablq (Pa, Pb, Ainc, Bine, x,y, z) STATIC^ 
SHARED Qx,Qy,Qz? 

1 => a,b = Polar coordinates of light source? 
1 p.a=anglel in XY-plane, pb is vertical? 
CALL Arctan(Ha,y, z,Qy,Qz)? 
CALL Arctan(Hb,x, z,Qx,Qz)? 
CALL Normal Angle (Pa, Ha+Ainc) ? 
CALL NormalAngle (Pb,Hb+Binc)? 
END SUB? 
'? 
'? 

SUB Mmlq3Test (n%, xl%,yl%, zl%, x2%, y2%, z2%, x3%,y3%, z3%) STATIC? 
SHARED True, False, Pi, AMin, BMin, AMax, BMax,Ainc, Bine, MinDist? 
1 => Determine min and max of a and b? 
ok!=True? 



? 



RepeatA:? 

CALL GETxyzlq(x,y, z , n%, xl%, yl %, zl%) ? 

CALL Disttest (x,y, z) ? 

CALL Calcablq(A.l,Bl,Ainc,Binc,x,y, z) ? 

CALL CETxyzlq(x,y, z, n%, x2%, y2%, z2%)? 

CALL j i st te s t (x , y , z ) ? 

CALL Caicablq(A2, B2, Ainc, Bine, x, y, z) ? 

CALL GETxyzlq(x,y,z,n%,x3%,y3%, z3%)? 

CALL Disttest (x,y, z) ? 

CALL Calcablq (A3, B3, Ainc, Bine, x,y,z)? 

CALL Deltasum3 (a, Al,A2,A3)? 

IF a>Pi THEN? 

' => Light source ' within ' triangle? 

AMin=-Pi? 

AMax-Pi? 

Ainc-Pi? 

ok! -True? 
ELSE? 

IF AKAMin THEN AMin - Al? 

IF A2<AMin THEN AMin = A2? 

IF A3<AMin THEN AMin = A3? 

? 

IF Al>AMax THEN AMax = Al? 

IF A2>AMax THEN AMax = A2? 

IF A3>AMax THEN AMax = A3? 

? 

IF (AMax-AMin>=Pi) AND (Ainc=0) THEN? 
Ainc-Pi? 
ok!=False? 



264 



Abacus Appendix B — The Tracer Program 



ELSE! 

ok!=TrueSI 
END IFSI 
END IFSI 



CALL Deltasum3(b,Bl,B2,B3)SI 
SI 

IF b>Pi THENSI 

' => Light source 'within' triangieSI 

BMin=-Pif 

BMax=PiSI 

Binc=PiSI 
ELSESI 

IF BKBMin THEN BMin = B1SI 

IF B2<BMin THEN BMin = B2SI 

IF B3<BMin THEN BMin = B3SI 

SI 

IF Bl>BMax THEN BMax = B1SI 

IF B2>BMax THEN BMax = B2SI 

IF B3>BMax THEN BMax = B3SI 

f 

±F (BMax-BMin>=Pi) AND (Binc=0) THENSI 
Binc=PiST 
ok! -Falser 

END IFSI 
END IFSI 

IF ok! <> True GOTO Repeat ASI 
END SUBSI 
'SI 

SUB Mrniq4Test (n%,xl%,yl%,zl%,x2%,y2%, z2%, x3%, y3%, z3%, x4%, y4%, z4 %) STATIC? 
SHARED True, False, Pi, Ainc, Bine, AMax, BMax, AMin,BMin,MinDistSI 
' => Determine min and max of a and b SI 
ok ! --TrueSI 
SI 
RepeatB: SI 

CALL GETxyzlq(x,y,z,n%,xl%,yl%, zl%)l 

CALL Disttest (x,y, z) SI 

CALL Calcablq(Al,Bl,Ainc,Binc,x,y, z) SI 

CALL GETxyzlq(x,y, z, n%, x2%, y2%, z2%) SI 

CALL Disttest (x,y, z) SI 

CALL Calcablq(A2,B2,Ainc,Binc,x,y, z) SI 

CALL GETxyzlq(x,y,z,n%,x3%,y3%,z3%)SI 

CALL Disttest (x,y, z) SI 

CALL Calcablq (A3, B3, Ainc, Bine, x,y, z) SI 

CALL GETxyzlq(x,y,z,n%,x4%,y4%, z4%)SI 

CALL Disttest (x,y, z) SI 

CALL Calcablq(A4,B4,Ainc,Binc,x,y, z) SI 

CALL Deltasum4 (a, Al , A2, A3, A4) SI 

IF a>Pi THEN SI 

' => Light source 'within' triangleSI 
AMin=-PiSI 
AMax=PiSI 
Ainc=PiSI 
ok!=TrueSI 



SI 



265 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



ELSESI 

IF AKAMin THEN AMin = AH 
IF A2<AMin THEN AMin = A2SI 
IF A3<AMin THEN AMin = A3SI 
IF A4<AMin THEN AMin = A4SI 
SI 

IF Al>AMax THEN AMax = AH 
IF A2>AMax THEN AMax = A2SI 
IF A3>AMax THEN AMax = A3SI 
IF A4>AMax THEN AMax = A4SI 
SI 

IF (AMax-AMin>=Pi) AND (Ainc=0) THENSI 
Ainc=PH 
ok!=FalseSI 
ELSESI 

ok!=TrueSi 
END IFfl 
END IFSI 
SI 

CALL Deltasum4 (b, Bl,B2,B3,B4)1 
SI 

IF b>Pi THENSI 

* => Light source 'within' triangleSI 
BMin=-PiSI 
BMax^PiSI 
Binc=PiSI 
ELSESI 

IF BKBMin THEN BMin = Bll 
IF B2<BMin THEN BMin = B2SI 
IF B3<BMin THEN BMin = B3SI 
IF B4<BMin THEN BMin = B4SI 
SI 

IF Bl>BMax THEN BMax = BH 
IF B2>BMax THEN BMax = B2SI 
IF B3>BMax THEN BMax = B3i 
IF B4>BMax THEN BMax = B4SI 
SI 

IF (BMax-BMin>=Pi) AND (Binc=0) THENSI 
Binc=PH 
ok!=FalseSI 
END IFSI 
END IF! 
IF ok! <> True GOTO RepeatBSl 
END SUB! 
'SI 

SUB MmlqKTest (n%,xl%,yl%, zl%, x2%,y2%, z2%,x3%,y3%, z3%, x4%, y4%, z4%) STATICS! 
SHARED True, False, Ainc, Bine, Pi, AMin, AMax, BMin, BMax, MinDistSI 
' => Determine min and max of a and bSI 
ok!=TrueSI 
SI 

RepeatC : SI 

CALL GETxyzlqk (x,y, z, n%,xl%, yl%, zl%) SI 
CALL Disttest (x,y, z) SI 
CALL Calcablq(Al,Bl,Ainc,Binc,x,y, z) 1 
SI 

CALL GETxyzlqk (x, y, z, n%, x2%,y2%, z2%) SI 
CALL Disttest (x,y, z) SI 

CALL Calcablq(A2,B2,Ainc,Binc,x,y, z) SI 
SI 

CALL GETxyzlqk (x, y, z, n%,x3%,y3%, z3%) SI 



266 



Abacus Appendix B — The Tracer Program 



CALL Disttest (x,y, z) SI 

CALL Calcablq(A3,B3,Ainc,Binc,x,y, z) f 
SI 

CALL GETxyzlqk(x,y,z,n%,x4%,y4%,z4%)SI 
CALL Disttest (x,y, z) SI 

CALL Calcablq(A4,B4,Ainc,Binc,x,y, z) SI 
SI 

CALL Deltasum4 (a, Al, A2, A3, A4) SI 
SI 

IF a>Pi THENSI 

' => Light source 'within' triangleSI 
AMin=-PiSI 
AMax=PiSI 
Ainc=PiSI 
ok!=TrueSI 
ELSESI 

IF AKAMin THEN AMin = All 
IF A2<AMin THEN AMin = A2SI 
IF A3<AMin THEN AMin = A3SI 
IF A4<AMin THEN AMin = A4SI 
SI 

IF Al>AMax THEN AMax = A1SI 
IF A2>AMax THEN AMax = A2SI 
IF A3>AMax THEN AMax = A3SI 
IF A4>AMax THEN AMax = A4SI 
SI 

IF (AMax-AMin>=Pi) AND (Ainc=0) THENSI 
Ainc=PiSI 
ok!=FalseSI 
ELSESI 

ok!=TrueSI 
END IFSI 
END IFSI 
SI 

CALL Deltasum4 (b,Bl,82,83,84)SI 
SI 

IF b>Pi THENSI 

' => Light source 'within' triangleSI 
BMin=-PiSI 
BMax=PiSI 
Binc=PiSI 
ELSESI 

IF BKBMin THEN BMin = BlSI 
IF B2<BMin THEN BMin = B2SI 
IF B3<BMin THEN BMin = B3SI 
IF B4<BMin THEN BMin = B4SI 
SI 

IF Bl>BMax THEN BMax = BlSI 
IF B2>BMax THEN BMax = B2SI 
IF B3>BMax THEN BMax = B3SI 
IF B4>BMax THEN BMax = B4SI 
SI 

IF (BMax-BMin>=Pi) AND (Binc=0) THENSI 
Binc=PiSI 
ok!=FalseSI 
END IFSI 
END IFSI 
IF ok!<>True THEN GOTO RepeatCSI 
END SUBSI 



267 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



SUB MmlqShpere(n%) STATIC! 

CALL MmlqKTest (n%, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1) SI 
CALL MmlqKTest (n%, -1 , -1, -1 , -1 , 1, -1, -1 , 1 , 1 , -1 , -1, 1) SI 
CALL MmlqKTest (n%, -1,1, -1,1, 1,-1, 1,1, 1,-1,1, 1)5 
CALL MmlqKTest (n%, 1,1, -1,1, -1,-1, 1,-1, 1,1, 1,1) SI 
CALL MmlqKTest (n%, 1, -1 , -1, -1, -1, -1, -1, -1, 1 , 1, -1, 1) SI 
CALL MmlqKTest (n%, -1,-1, 1,-1, 1,1, 1,1, 1,1,-1, 1)5 
END SUBSI 
'SI 
SUB MmlqCylinder (n%) STATICS! 

CALL Mmlq4Test(n%, -1,-1, 0,-1, 1,0, 1,1, 0,1, -1,0) SI 
CALL Mmlq4Test (n%, -1 , -1, 0, -1 , 1 , , -1 , 1 , 1 , -1 , -1 , 1 ) SI 
CALL Mmlq4Test (n%, -1, 1, 0, 1, 1, 0, 1, 1, 1, -1 , 1 , 1) SI 
CALL Mmlq4Test (n%, 1 , 1 , 0, 1, -1, 0, 1, -1 , 1, 1, 1 , 1) SI 
CALL Mmlq4Test (n%, 1, -1 , 0, -1, -1 , 0, -1, -1, 1, 1, -1, 1 ) SI 
CALL Mmlq4Test (n% , -1 , -1 , 1 , -1 , 1 , 1 , 1 , 1 , 1 , 1 , -1 , 1 ) SI 
END SUBSI 
'SI 
SUB MmlqCone(n%) STATICSI 

CALL Mmlq4Test(n%, -1,-1, 0,-1, 1,0, 1,1, 0,1,-1, 0) SI 
CALL Mmlq3Test (n%, -1, -1, 0, -1 , 1 , 0, 0, 0, 1) SI 
CALL Mmlq3Test (n%,-l, 1, 0,1, 1, 0, 0, 0,1)SI 
CALL Mmlq3Test(n%, 1,1, 0,1, -1,0, 0,0,1) SI 
CALL Mmlq3Test (n%, 1, -1 , 0, -1, -1, 0, 0, 0, 1) SI 
END SUBSI 
'SI 
SUB MmlqEllipsoid(n%) STATICSI 

CALL Mmlq4Test(n%, -1,-1, -1,-1, 1,-1, 1,1, -1,1, -1,-1) SI 
CALL Mmlq4Test (n%, -1 , -1, -1, -1 , 1 , -1, -1 , 1 , 1, -1, -1, 1 ) SI 
CALL Mmlq4Test(n%, -1,1, -1,1, 1,-1, 1,1, 1,-1, 1,1) SI 
CALL Mmlq4Test(n%, 1,1, -1,1, -1,-1, 1,-1, 1,1, 1,1) SI 
CALL Mmlq4Test (n%, 1, -1 , -1, -1, -1, -1, -1, -1, 1, 1, -1, 1) SI 
CALL Mmlq4Test(n%, -1,-1, 1,-1, 1,1, 1,1, 1,1, -1,1) SI 
END SUBSI 
'SI 
'SI 
InitMinmaxLqrSI 

' => Compute surface interval for shadow computation in polar coordinates^! 
' a = angle of X-Axis, b = angle of Y-Axis, mindist = minimum distance to light 
source SI 

ERASE minmaxlqSI 
DIM minmaxlq(NumberK, 6) SI 
SI 

FOR n%=l TO NumberKSI 
AMin=PiSI 
AMax=-Pif 
BMin=PiSI 
BMax=-PiSI 
Ainc=0SI 
Binc=0SI 
MinDist=- 1SI 
SI 

IF K(n%,0,0)=0 THENSI 
AMin=- Pi SI 
BMin=-PiSI 
AMax=PiSI 
BMax=PiSI 

MinDist=ABS(Help(n%, 0) * (Qx-K (n%, 1, 0) ) +Help(n%, 1) * (Qy- 
K(n%,l,l) )+Help(n%,2)*(Qz-K(n%,l,2)))SI 
END IFSI 



268 



Abacus Appendix B — The Tracer Program 



IF K(n%,0,0)=l THEN5 

CALL Mmlq3Test (n%, 0,0, 0,0,1,0,1,0,0)5 
END IFfl 

IF K(n%,0,0)=2 THENSI 

CALL Mmlq4Test(n%, 0,0, 0,0, 1,0, 1,0, 0,1, 1,0)5 
END IF5 

IF (K(n%,0,0)>=3) AND (K (n%, 0, 0) <6) THEM 

CALL Mmlq4Test (n%, -1,-1, 0,-1, 1,0, 1,-1, 0,1, 1,0) < 
END IF5 

IF K(n%,0,0)=10 THEN5 

CALL MmlqShpere(n%)5 
END IF5 

IF (K(n%,0,0)=20) OR (K(n%, 0, 0) =21) THEM 

CALL MmlqCylinder(n%)f 
END IF5 

IF K(n%, 0,0) =22 THEN5 

CALL MmlqCone(n%)5 
END IF5 

IF K(n%,0,0)=24 THEN5 

CALL MmlqEllipsoid(n%)5 
END IF5 



5 



minmaxlq (n%, 0) =Ainc5 
minmaxlq(n%, l)=AMin5 
minmaxlq (n%, 2) =AMax5 
minmaxlq (n%, 3) =Binc5 
minmaxlq (n%, 4)=BMin5 
minmaxlq (n%, 5)=BMax5 
minmaxlq (n%, 6) =MinDist ( I 
NEXT n%5 

RETURNS 

'END of SHADOW-INIT.ascI 



269 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



The SHADOWING.ASC module 



START of SHADOWING. ASCSI 

• •••••••••••••••••••••••••••••••*<j[ 

* Shadowing *fl 

SUB IntersectpointPlane (n%, Px, Py,Pz, Rx,Ry, Rz, 1) STATIC^ 
SHARED Help() ,K() f 

1 => 1 = exact parameter^ 

D=Ry*Help (n%, 4) -Rx*Help (n%, 3 ) -Rz*Help (n%, 5) f 

IF DOO THEN^I 

1=( (Px-K (n%, 1,0) ) *Help(n%,3)-(Py-K(n%,l,l))*Help(n%,4)+ (Pz- 
K(n%,l,2) )*Help(n%,5) ) /Df 

ELSESI 

END IF5 
END SUB1 

SUB IntersectpointTriangle (n%,Px, Py,Pz, Rx,Ry, Rz, 1, a,b) STATICSI 
SHARED HelpO , K ( ) SI 

' => 1 = exact parameter, a,b = area parameter^ 
D=Ry*Help (n%, 4) -Rx*Help (n%, 3) -Rz*Help (n%, 5) $ 
IF DOO THENf 

1= ( (Px-K (n%, 1, 0) ) *Help (n%, 3) - (Py-K (n%, 1, 1) ) *Help (n%, 4) + (Pz- 
K (n%, 1, 2) ) *Help (n%, 5) ) /Df 
IF 1>0 THEN! 

a=FN Det (Px-K (n%, 1,0) ,K (n%, 3, 0) , -Rx, Py-K (n%, 1, 1) , K (n%, 3, 1) , -Ry, Pz- 
K(n%,l,2),K(n%,3,2) , -Rz)/Dl 

b=FN Det (K(n%,2, 0) , Px-K(n%, 1, 0) , -Rx,K (n%, 2, 1) ,Py-K(n%, 1, 1) , -Ry,K (n%, 2, 2) ,Pz- 
K(n%,l,2) ,-Rz)/Dfl 

IF a<0 OR b<0 OR a>l OR b>l OR a+b>l THEN! 

l=-lfl 
END IF! 
END IF! 
ELSE! 

1=-1! 
END IF! 
END SUB! 
'1 

SUB IntersectpointRectangle (n%, Px,Py, Pz,Rx, Ry,Rz, 1, a, b) STATIC! 
SHARED HelpO ,K()! 

' => 1 = exact parameter, a,b = area parameter*! 
D=Ry*Help (n%, 4) -Rx*Help (n%, 3) -Rz*Help (n%, 5) ! 
IF DOO THEN! 

1= ( (Px-K (n%, 1, 0) ) *Help (n%, 3) - (Py-K (n%, 1, 1) ) *Help (n%, 4) + (Pz- 
K (n% , 1 , 2) ) *Help (n%, 5) ) /D! 
IF 1>0 THEN! 

a=FN Det (Px-K (n%, 1, 0) , K (n%, 3, 0) , -Rx, Py-K (n%, 1 , 1 ) ,K(n%,3,l) , -Ry,Pz- 
K(n%,l,2) , K(n%,3,2),-Rz)/D! 

b=FN Det (K(n%,2,0) , Px-K (n%, 1, 0) , -Rx,K (n%, 2, 1) , Py-K (n%, 1 , 1 ) , -Ry , K (n%, 2, 2) ,Pz- 
K(n%,l,2) ,-Rz)/D! 

IF a<0 OR b<0 OR a>l OR b>l THEN! 



270 



Abacus Appendix B — The Tracer Program 



l=-im 

END IF! 
END IF! 
ELSE! 

1=-1! 
END IF! 
END SUB! 
'! 

SUB IntersectpointCircle (n%, Px, Py, Pz, Rx f Ry, Rz, l,a,b) STATIC! 
SHARED Kelp() ,K()! 

1 => 1 = exact parameter, a,b = area parameter! 
D=Ry*Help (n%, 4) -Rx*Help (n%, 3) -Rz*Help (n%, 5) f 
IF DOO THEN! 

1= ( (Px-K (n%, 1, 0) ) *Help (n%, 3) - (Py-K (n%, 1, 1) ) *Help (n%, 4) + (Pz- 
K (n%, 1, 2) ) *Help (n%, 5) ) /D! 
IF 1>0 THEN! 

a=FN Det (Px-K (n%, 1,0) ,K(n%,3,0) , -Rx,Py-K (n%, 1, 1 ) ,K(n%,3,l) , -Ry^z- 
.K (n%, 1, 2) , K (n%, 3, 2) , -Rz) /D! 

b=FN Det (K(n% / 2 / 0) ,Px-K(n%, 1, 0) , -Rx,K (n%, 2, 1) , Py-K (n%, 1 , 1 ) , -Ry, K (n%, 2, 2) ,Pz 
K(n%,l,2),-Rz)/D! 
! 

IF a*a+b*b>l THEN! 

1 — 1! 
END IF! 
END IF! 
ELSE! 

1--1! 
END IF! 
END SUBS! 



SUB Anglelntervall (l,n%,a,b) STATIC! 
SHARED Pi,Pm2,Pd2,K()! 
IF a=0 THEN! 

D=Pd2*SGN(b)! 
ELSE! 

D=ATN(b/a)! 

IF a<0 THEN! 
D = D+Pi! 

END IF! 
END IF! 
IF D<0 THEN! 

D = D+Pm2! 
END IF! 
IF D<K(n%,5,0) OR D>K(n%,5,l) THEN! 

1—1! 

END IF! 
END SUB! 
■! 
'! 

SUB Inter sectpointCircleSect or (n%, Px, Py , Pz, Rx, Ry , Rz , 1 , a, b) STATIC! 
SHARED HelpO ,K()! 

1 => 1 = exact parameter, a,b = area parameter! 
D=Ry*Help(n%, 4) -Rx*Help (n%, 3) -Rz*Heip (n%, 5) ! 
IF DOO THEN! 

1=( (Px-K (n%, 1,0) ) *Help(n%,3)-(Py-K(n%,l,l) ) *Help (n%, 4 ) ■+ (Pz- 
K(n%,l,2) )*Help(n%,5) ) /D! 
IF 1>0 THEN! 

a=FN Det (Px-K (n%, 1,0) ,K(n%,3,0) , -Rx, Py-K (n%, 1 , 1 ) , K (n% , 3, 1 ) , -Ry,Pz- 
K (n%, 1 , 2) , K (n%, 3, 2) , -Rz) /Df 



271 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



b=FN Det (K(n%,2,0) ,Px-K(n%, 1, 0) , -Rx,K (n%, 2, 1) , Py-K (n%, 1, 1 ) , -Ry, K (n%, 2, 2) ,Pz- 
K(n%,l,2) ,-Rz)/Dfl 

IF a*a+b*b<=l THENS 

CALL AngleIntervall(l,n%,a,b)S 
ELSE5 

1=-H 
END IFfl 
END IFfl 
ELSESI 

l=-lfl 
END IFSI 
END SUBfl 
'5 

SUB IntersectpointCircleRing(n%,Px,Py,Pz,Rx,Ry,Rz, l,a,b) STATICf 
SHARED HelpO ,K()f 

1 => 1 = exact parameter, a,b = area parameter^ 
D=Ry*Help(n%, 4) -Rx*Help (n%, 3) -Rz*Help (n%, 5) <3I 
IF DO0 THEN«5I 

1=( (Px-K (n%, 1,0) )*Help(n%,3)-(Py-K(n%,l,l))*Help(n%,4)+ (Pz- 
K(n%,l,2) )*Help(n%,5) ) /DSI 
IF 1>0 THENSI 

a=FN Det (Px-K (n%, 1, 0) ,K(n%,3,0) , -Rx,Py-K (n%, 1 , 1 ) ,K(n%,3,l) , -Ry,Pz- 
K(n%,l,2) ,K(n%,3,2),-Rz)/D$ 

b=FN Det (K(n%,2,0) , Px-K (n%, 1 , 0) , -Rx,K (n%, 2, 1) ,Py-K (n%, 1, 1 ) , -Ry,K (n%, 2, 2) ,Pz- 
K(n%,l,2) ,-Rz)/Dfl 

D=SQR(a*a+b*b)Sl 

IF (D>=K(n%,4,0)) AND (D<=K(n%, 4, 1) ) THEN^l 

CALL Anglelntervall (l,n%, a,b) <R 
ELSESI 

l=-lf 
END IFf 
END IF1 
ELSE5 

l=-lfl 
END IFfl 
END SUBS 

SUB IntersectpointSphere(n%,Px,Py,Pz,Rx,Ry,Rz,l) STATICS 
SHARED HelpO ,K() , Thresholds 
' => 1 = exact parameter^! 
D=Rx*Rx+Ry*Ry+Rz*Rzf 

p=(Rx* (Px-K (n%, 1,0) )+Ry* (Py-K (n%, 1, 1) )+Rz* (Pz-K(n%, 1,2) ) ) /Df 

q=( (Px-K (n%, 1,0) ) A 2+ (Py-K (n%, 1,1) ) A 2+ (Pz-K (n%, 1 , 2) ) A 2-K (n%, 2, 0) *K(n%,2,0) ) /DS 
D=p*p-qS 
IF D>=0 THENS 
l=-p+SQR(D)S 
Ll=-p-SQR(D)Sl 
IF (LK1) AND (Ll>Threshold) THENS 

SWAP 1,L1S 
END IFS 
ELSES 

l=-lfl 
END IFf 
END SUBS 



SUB Basistrans (n%, Pxt, Pyt, Pzt, Xt, Yt, Zt,Px, Py, Pz,Rx, Ry, Rz, Original ! ) STATICS 
SHARED HelpO ,K()S 



272 



Abacus Appendix B — The Tracer Program 



' Transform (px,py,zy) => (pxt,pyt,pzt) , (rx,ry,rz) => (xt, yt , zt) SI 
IF Original! = True THENSI 
Pxt=Help(n%,10)f 
Pyt=Help(n%,ll)fl 
Pzt=Help(n%,12)SI 
ELSESI 

Pxt=(Px-K(n%,l,0) ) *Help(n%,I3)-(Py-K(n%,l,l) ) *Help (n%, 14 ) + (Pz- 
K(n%,l,2) ) *Help(n%, 15) ^ 

Pyt=(Px-K(n%,l,0) ) *Help (n%, 1 6) - (Py-K (n%, 1, 1) ) *Help (n%, 17) + (Pz- 
K(n%,l,2) )*Help(n%,18)fl 

Pzt=(Px-K(n%,l,0) )*Help(n%,19)-(Py-K(n%,l,l) ) *Help (n%, 20) + (Pz- 
K(n%,l,2) )*Help(n%, 21)31 
END IFSI 

Xt= (Px+Rx-K (n%, 1, 0) ) *Help (n%, 13) - (Py+Ry-K (n%, 1, 1) ) *Help (n%, 14) + (Pz+Rz- 
K (n%, 1 , 2) ) *Help (n%, 15 ) -Pxtf 

Yt= (Px+Rx-K (n%, 1,0)) *Help (n%, 16) - (Py+Ry-K (n%, 1,1)) *Help (n%, 17) + (Pz+Rz- 
K (n%, 1, 2) ) *Help (n%, 18) -PytSI 

Zt= (Px+Rx-K (n%,l, 0) ) *Help(n%, 19)- (Py+Ry-K (n%, 1,1) ) *Help (n%, 20) + (Pz+Rz- 
K(n%,l,2))*Help(n%,21)-Pztf 
END SUBSI 
x f 

"31 

SUB IntersectpointCylinder (n%, Px, Py, Pz,Rx, Ry,Rz, l,a,b, c, Original ! ) STATICS! 

SHARED Thresholds 

• => l=exact parameter, a,b,c = transform Intersect point coordinates^ 
CALL Basistrans (n%, Pxt , Pyt , Pzt, Xt , Yt, Zt, Px, Py, Pz, Rx, Ry, Rz, Original ! ) SI 
D=Xt*Xt+Yt*YtSl 
IF DO0 THENSI 

p= (Pxt*Xt+Pyt*Yt) /DSI 
q= (Pxt*Pxt+Pyt*Pyt-l) /DSI 
D=p*p-qSI 
IF D>=0 THENSI 
1— p+SQR(D)SI 
Ll=-p-SQR(D)SI 
c=Pzt+l*ZtSI 
D=Pzt+Ll*ZtSI 

IF LK1 AND Ll>Threshold AND D>=0 AND D<=1 THENSI 
SWAP 1,L1SI 
SWAP c,DSI 
END IFS1 
IF c<0 OR Ol THENSI 

1=-1SI 
ELSESI 

a=Pxt + l*XtSI 
b=Pyt + l*YtSI 
END IFSI 
ELSESI 

1—1SI 
END IFSI 
ELSESI 

1= — 1ST 
END IFSI 
END SUBSI 
'SI 

SUB I nter sect point Cy linderSegm(n%,Px / Py,Pz,Rx,Ry / Rz,l, a, b,c, Original! ) STATIC^ 
SHARED Threshold SI 

' => l=exact parameter, a,b,c = transform Intersect point coordinatesSI 
CALL Basistrans (n%, Pxt , Pyt , Pzt, Xt, Yt, Zt, Px, Py, Pz, Rx, Ry, Rz, Original ! ) SI 
D=Xt*Xt+Yt*YtSI 
IF DO0 THENSI 



273 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



p= (Pxt*Xt+Pyt*Yt) /D! 
q= (Pxt*Pxt+Pyt*Pyt-l) /Df 
D=p*p-q! 
IF D>=0 THEN! 
l=-p+SQR(D)! 
Ll=-p-SQR(D)! 
c=Pzt+l*Zt! 
Cl=Pzt+Ll*Zt! 
IF 0=0 AND c<=l THEN! 

CALL Anglelntervall (1, n%, Pxt+l*Xt, Pyt+l*Yt) ! 
ELSE! 

1=-1! 
END IF! 
IF C1>=0 AND C1<=1 THEN! 

CALL Anglelntervall (LI, n%, Pxt+Ll*Xt, Pyt+Ll*Yt ) ! 
ELSE! 

Ll=-1! 
END IF! 

IF (K-.5) OR (LK1 AND Ll>Threshold) THEN! 
SWAP 1,L1! 
SWAP c,Cl! 
END IF! 
a=Pxt+l*Xt! 
b=Pyt+l*Yt! 
ELSE! 

1=-1! 
END IF! 
ELSE! 

i=-i! 

END IF! 
END SUB! 
'! 

SUB Inter sect pointCone (n%, Px, Py,Pz, Rx, Ry, Rz, 1, a, b, c, Original ! ) STATIC! 
SHARED Threshold! 

' => l=exact parameter, a.b.c = transform Intersect point coordinates! 
CALL Basistrans(n%,Pxt,Pyt,Pzt,Xt,Yt,Zt,Px,Py,Pz,Rx,Ry,Rz, Original! )! 
D=Xt*Xt+Yt*Yt-Zt*Zt! 
IF DOO THEN! 

p= (Pxt*Xt+Pyt*Yt+Zt* (1-Pzt) ) /D! 
q= (Pxt*Pxt+Pyt*Pyt- (1-Pzt) A 2) /D! 
D=p*p-q! 
IF D>=0 THEN! 
l = -pfSQR(D)! 
LI— p-SQR(D)! 
c=Pzt+l*Zt! 
D=Pzt+Ll*Zt! 

IF LK1 AND Ll>Threshold AND D>=0 AND D<=1 THEN! 
SWAP 1,L1! 
SWAP c,Di 
END IF! 
IF c<0 OR c>l THEN! 

1=-1! 
ELSE! 

a=Pxt+l*Xt! 
b=Pyt+l*Yt! 
END IF! 
ELSE! 

1=-1! 
END IF! 
ELSE! 



274 



Abacus Appendix B — The Tracer Program 



i=-i! 

END IF! 
END SUB! 
'! 

SUB IntersectpointEllipsoid(n%,Px,Py,Pz,Rx,Ry,Rz, 1, a, b, c, Original ! ) STATIC 
SHARED Threshold! 

' => l=exact parameter, a,b,c = transform Intersect point coordinates! 
CALL Basistrans(n%,Pxt,Pyt,Pzt,Xt,Yt, Zt , Px, Py, Pz, Rx, Ry, Rz, Original ! ) SI 
D=Xt*Xt+Yt*Yt+Zt*Zt! 
IF DOO THEN! 

p= (Pxt*Xt+Pyt*Yt+Pzt*Zt) /D! 
q= (Pxt*Pxt+Pyt*Pyt+Pzt*Pzt-l) /D! 
D=p*p-q! 
IF D>=0 THEN! 
l=-p+SQR(D)! 
Ll=-p-SQR(D)! 
IF LK1 AND Ll>Threshold THEN! 

SWAP 1,L1! 
END IF! 
a=Pxt+l*Xt! 
b=Pyt+l*Yt! 
c=Pzt+l*Zt! 
ELSE! 

1=-1! 
END IF! 
ELSE! 

1=-1! 
END IF! 
END SUB! 



SUB WhichBody (Kp%,Px, Py, Pz, Rx, Ry, Rz, Original !, Shadown! ) STATIC! 

SHARED 

True, False, minmax%() , NumberK, minmaxlq () ,Help() ,K() ,xb%,yb%,Sx, Sy, Sz, Body%, Ac, Be, Cc, 

la, Threshold! 

1 => Body% = Nr the body under coordinates xb%,yb%, S (sx, sy, sz) =Intersect point, 
la=intersection line! 

• => if Typ>=20: (ac,bc,cc) = transform Intersect point coordinates! 
la=-l! 
Body%=0! 
! 

IF Shadown! = True THEN ! 

CALL Calcablq (Anglea, Angleb, ! , ! , Px, Py, Pz) ! 
Di st=SQR (Rx*Rx+Ry*Ry+Rz*Rz ) ! 
END IF! 
! 

FOR n%=l TO NumberK! 

IF Original! = True THEN! 
IF minmax%(n%,0)>xb% THEN! 

GOTO Nxtk! 
END IF! 
IF minmax%(n%,l)>yb% THEN! 

GOTO Nxtk! 
END IF! 
IF minmax%(n%,2)<xb% THEN! 

GOTO Nxtk! 
END IF! 
IF minmax%(n%, 3)<yb% THEN! 

GOTO Nxtk! 
END IF! 



275 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



END IF! 

! 

IF Shadown! = True THEN! 

CALL NormalAngle (Wa, Anglea+minmaxlq(n%, 0) ) ! 

CALL NormalAngle (Wb, Angleb+minmaxlq(n%, 3) ) ! 

IF Wa<minmaxlq(n%,l) THEN! 
GOTO Nxtk! 

END IF! 

IF Wa>minmaxlq(n%,2) THEN! 
GOTO Nxtk! 

END IF! 

IF Wb<minmaxlq(n%,4) THEN! 
GOTO Nxtk! 

END IF! 

IF Wb>minmaxlq(n%,5) THEN! 
GOTO Nxtk! 

END IF! 

IF Dist<minmaxlq(n%,6) THEN! 
GOTO Nxtk! 

END IF! 
END IF! 
! 
IF K(n%,0,0)=0 THEN! 

CALL IntersectpointPlane(n%,Px,Py,Pz,Rx,Ry,Rz,l)! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=l THEN! 

CALL IntersectpointTriangle (n%, Px, Py, Pz, Rx, Ry, Rz, 1, a, b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=2 THEN! 

CALL IntersectpointRectangle (n%,Px, Py,Pz, Rx, Ry, Rz, 1, a,b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)-3 THEN! 

CALL IntersectpointCircle(n%,Px,Py,Pz,Rx,Ry,Rz, l,a,b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=4 THEN! 

CALL Inter sectpointCircleSect or (n%, Px,Py, Pz,Rx, Ry,Rz, 1, a, b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=5 THEN! 

CALL IntersectpointCircleRing (n%,Px, Py,Pz, Rx, Ry,Rz, 1, a, b) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=10 THEN! 

CALL IntersectpointSphere (n%, Px, Py, Pz, Rx, Ry , Rz, 1) ! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=20 THEN! 

CALL IntersectpointCylinder (n%,Px,Py,P z, Rx,Ry, Rz, 1, a, b,c, Original! )! 

GOTO Wkok! 
END IF! 
IF K(n%,0,0)=21 THEN! 

CALL Inter sect pointCylinderSegm(n%, Px,Py, Pz,Rx, Ry,Rz, 1, a, b, c, Original ! )! 

GOTO Wkok! 
END IF! 
IF K(n%, 0,0) =22 THEN! 

CALL IntersectpointCone (n%, Px,Py,Pz, Rx,Ry, Rz, 1, a, b, c, Original ! )! 



276 



Abacus Appendix B — The Tracer Program 



GOTO WkokSI 
END IFSI 
IF K(n%,0,0)=24 THENSI 

CALL IntersectpointEllipsoid(n%,Px,Py,Pz,Rx,Ry,Rz, 1 , a, b, c, Original ! ) SI 
END IFSI 
Wkok:SI 
' Work OK! SI 
SI 

IF (l>Threshold) AND (la<=0 OR Kla) AND (n%<>Kp% OR K (n%, 0, 0) >=10) THENSI 
la=lSI 
Body%=n%SI 

IF K(n%,0,0)>=20 AND Kp%=0 THENSI 
Ac=aSI 
Bc=bSI 
Cc=cSI 
END IFSI 
END IFSI 
Nxtk:SI 
1 Next bodySI 
NEXT n%SI 
SI 

IF Body%>0 AND Kp%=0 THENSI 
Sx=Px+la*RxSI 
Sy=Py+la*RySI 
Sz=Pz + la*RzSI 
END IF SI 
END SUBSI 



SUB SetBrightness(n%,Px,Py,Pz, Mirror, Original!) STATICSI 

SHARED HelpO ,K() , Mat () ,Qx, Qy,Qz, Ac, Be, Cc, Sx, Sy, Sz, Nx, Ny, Nz , Nl, Spx, Spy , Spz, Bright 

SI 

1 => Bright =Brightness, SP=Mirror Vector, Mirror=Intensity of LQ-MirroringSI 
SI 

IF K(n%,0,0)<=9 THENSI 

1 Determine Mirror Vektor SPSI 
Nx=Help(n%,0)SI 
Ny=Help(n%,l)SI 
Nz=Help(n%,2)SI 
IF Original ! <>True THENSI 

IF FN CosinAngle(Nx,Ny,Nz,Px-Sx,Py-Sy,Pz-Sz)<0 THENSI 
'Normal vector must point to projection point! SI 
Nx=-NxSI 
Ny=-NySI 
Nz=-NzSI 
END IFSI 
END IFSI 

Dqe=Nx* (Qx-Sx) +Ny* (Qy-Sy) +Nz* (Qz-Sz) SI 
SI 

Spx=Sx-Qx+2*Dqe*NxSI 
Spy=Sy-Qy+2*Dqe*NySI 
Spz=Sz-Qz+2*Dqe*NzSI 
SI 

Mirror=FN CosinAngle (Spx, Spy, Spz, Px-Sx, Py-Sy, Pz-Sz) SI 
SI 

IF Mirror<0 THENSI 

Mirror=0SI 
END IFSI 
SI 

Bright=FN CosinAngle (Nx, Ny, Nz, Qx-Sx, Qy-Sy, Qz-Sz) SI 



277 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



ELSEl 

' Determine mirror vector SPSI 
IF K(n%,0,0)=10 THEN1 
Nx=Sx-K(n%,l, 0)1 
Ny=Sy-K(n%, 1,1)31 
Nz=Sz-K(n%, 1,2)1 
END IFl 

IF K(n%,0,0)>=20 AND K(n%,0,0)<24 THEN1 
Nx^Help (n%, 4) *Ac+Help (n%, 1) *Bc1 
Ny=Help (n%, 5 ) *Ac+Help (n%, 2) *Bc1 
Nz=Help (n%, 6) *Ac+Help (n%, 3) *Bc1 

IF K(n%,0,0)>=22 THEN1 

N1=SQR (Nx*Nx+Ny*Ny+Nz*Nz) 1 
IF NloO THEN1 

a= (Ac*K (n% ,2,0) +Bc*K (n%, 3, 0) ) "21 

a=a+ (Ac*K (n%, 2, 1) +Bc*K (n%, 3, 1 ) ) "21 

a=(SQR(a+ (Ac*K (n%, 2 , 2) +Bc*K (n%, 3, 2 ) ) A 2) ) /Nil 

Nx = Nx*a1 

Ny = Ny*a1 

Nz - Nz* al 

b=SQR (Nx*Nx+Ny*Ny+Nz*Nz) /Help (n%, 7) 1 

Nx=K(n%, 4,0) *b+Nx/b1 

Ny=K(n%, 4, 1) *b+Ny/b1 

Nz=K(n%,4,2) *b+Nz/b1 
ELSEl 

1 If a cone anglerl 

Nx=K(n%, 4,0)31 

Ny=K(n%, 4,1)1 

Nz=K(n%, 4,2)1 
END IFl 
END IFl 
END IFl 

IF K(n%,0,0)>=24 THEN1 

Nx=Ac*Help (n%, 1) +Bc*Help (n%, 4) +Cc*Help (n%, 7 ) 1 
Ny=Ac*Help (n%, 2) +Bc*Help (n%, 5) +Cc*Help (n%, 8 ) 1 
Nz=Ac*Help(n%,3) +Bc*Help(n%, 6) +Cc*Help (n%, 9) 1 

END IFl 

IF FN CosinAngle(Nx,Ny,Nz,Px-Sx,Py-Sy,Pz-Sz) <0 THENl 
1 => Normal vector points to projection pointl 

Nx=- Nxl 

Ny=-Ny1 

Nz=-Nzf 
END IFl 

Nl=SQR(Nx*Nx+Ny*Ny+Nz*Nz)1 
Nx = Nx/Nll 
Ny = Ny/Nll 
Nz - Nz/Nll 

Dqe=Nx* (Ox-Sx) +Ny* (Qy-Sy) +Nz* (Qz-Sz) 1 

Spx=Sx-Qx+2*Dqe*Nx1 
Spy=Sy-Qy+2*Dqe*Ny1 
Spz=Sz-Qz+2*Dqe*Nz1 

Mirror=FN CosinAngle (Spx, Spy, Spz, Px-Sx, Py-Sy, Pz-Sz) 1 



SI 
1 

278 



Abacus Appendix B — The Tracer Program 



IF Mirror<0 THEN! 

Mirror=0! 
END IF! 



Bright=FN CosinAngle (Nx, Ny, Nz, Qx-Sx, Qy-Sy, Qz-Sz) ! 
END IF! 
! 

IF Mat(K(n%,0,2) ,4)>0 THEN! 

Mirror=l . 5*Mirror A (30*Mat (K (n%, 0, 2) , 4) ) ! 
END IF! 
END SUB! 
'! 
'! 

SUB StandardFill(xl%,yl%,x2%,y2%, Bright, Coll%,Col2%) STATIC! 
SHARED PatternHS () , PatternS&, NumberPatternS%, RastPort&! 
' draw rectangle in standard fill pattern! 
Min=lE+35! 
Nr%=0! 
n%=0! 
! 

WHILE ABS (Bright-PatternHS (n%) ) <Min! 
' sort in ascending order! 
Min=ABS (Bright-PatternHS (n%) ) ! 
Nr%=n%! 
n% = n% +1! 

IF n%>=NumberPatternS% GOTO ContinueA! 
WEND! 
! 

ContinueA:! 

CALL SetAPen& (RastPort&,Coll%) ! 
CALL SetBPen&(RastPort&,Col2%)! 
! 

POKEL RastPort&+8, (PatternS&+Nr%*32) ! 

1 RastPort->AreaPtrn = & (PatternS% (0, Nr%) ! 
! 
POKE RastPort&+29,4! 

' RastPort->AreaPtSz = 4 (=> 4 A 2 = 16)! 
! 

CALL RectFill&{RastPort&,xl% / yl%,x2% / y2%)! 
END SUB ! 
'! 

SUB ExtendedFill(xl%,yl%,x2%,y2%, Bright, Brightl,Bright2,Coll%,Col2%) STATIC! 
SHARED NumberPatternX%,PatternHX(),PatternX&,RastPort& ! 
1 draw rectangle in standard fill pattern! 
' binary search for optimal pattern ! 
m= (Bright-Brightl ) / (Bright2-Brightl ) ! 
Min=lE+35! 
Nr%=0! 

Ug%=0 'top limit! 

Og%=NumberPatternX%*2 'lower limit! 
! 

Repeat3:! 

Mitte%=INT ( (Ug%+Og%) 12) ! 
IF ABS(m-PatternHX(Mitte%) ) <Min THEN! 
Min=ABS (m-PatternHX (Mitte%) ) ! 
Nr%=Mitte%! 
END IF! 
IF m>PatternHX(Mitte%) THEN! 

Ug%=M.itte%+l! 
ELSE! 



279 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



Og%=Mitte%-15 
END IF5 
IF (Ug%<=Cg%) AND (Min<>0) THEN GOTO Repeat 35 
5 

CALL SetAPen& (RastPort&,Coll%)5 
CALL SetBPen& (RastPort&,Col2%) 5 
5 

POKEL RastPort&+8, (PatternX&+Nr%*32) ' s.o. 5 
POKE RastPort&+29,45 
5 

CALL RectFill&(RastPort&,xl%,yl%,x2%,y2%)5 
END SUB5 
'5 

SUB SetPoint (xl%,yl%,x2%, y2%, Bright . r, Bright .g, Bright .b) STATIC5 
SHARED MaxColour%, Colour () ,RasterHl%,RasterWl%,RastPort&5 
SHARED NumberPatternX%,PatternX&, PatternHX () 5 
IF x2%>RasterWl% THEN x2%=RasterWl%5 
IF y2%>RasterHl% THEN y2%=RasterHl%5 
5 

'search colors for simialr color tone:5 
5 

Min=lE+105 
Nrl%=15 
5 

'Convert colors to Polar coordinates :5 
5 

dh=SQR (Bright . r*Bright . r+Bright . g*Bright . g) 5 
IF dh>0 THEN5 

IF Bright. r>0 THEN5 

ah=ATN (Bright . g/Bright . r ) 5 
ELSE5 

ah=l. 57085 
END IF5 

bh=ATN(Bright.b/dh)5 
dh=SQR (dh*dh+Bright . b*Bright .b) 5 
ELSE5 

a=. 78545 

IF Colour (n%, 3) =0 THEN5 

b=. 78545 
ELSE5 

b=l. 57085 
END IF5 
END IF5 
5 

'search for optimim colors:5 
5 

FOR n%=l TO MaxColour%5 

D=SQR (Colour (n%, 1) A 2+Colour (n%, 2) A 2) 5 
IF D>0 THEN5 

IF Colour (n%,l)>0 THEN5 

a=ATN (Colour (n%, 2) /Colour (n%, 1) ) 5 
ELSE5 

a=l. 57085 
END IF5 

b=ATN (Colour (n%, 3) /D) 5 
D=SQR (D*D+Colour (n%, 3) *Colour (n%, 3) ) 5 
ELSE5 

a=. 78545 

IF Colour (n%, 3) =0 THEN5 
b=. 78545 



280 



Abacus Appendix B — The Tracer Program 



ELSESI 

b=1.5708f 
END IFSI 
END IFSI 

h= (a-ah) A 2 + (b-bh) A 2+ABS (D-dh) 1 
IF h<Min THENSI 
Min=hSI 
Nrl%=n%SI 
END IFSI 
NEXT n%SI 
SI 

'Determine best pattern and second color for color combination*! 
SI 

Min=lE+10SI 
NrM%=0SI 
Nr2%=lf 

FOR n%=0 TO NumberPatternX%SI 
FOR Nr%=0 TO MaxColour%SI 
IF Nr%ONrl% THENSI 

h.r=PatternHX(n%) *Colour(Nrl%,l)+ (1-PatternHX (n%) ) *Colour (Nr%, 1) SI 
h.g=PatternHX (n%) *Colour (Nrl%, 2) + (1-PatternHX (n%) ) *Colour (Nr%, 2) SI 
h.b=PatternHX (n%) *Colour (Nrl%, 3) + (1-PatternHX (n%) ) *Colour (Nr%, 3) SI 
h= (Bright, r-h.r) A 2+ (Bright. g-h.g) A 2+ (Bright, b-h.b) A 2SI 
IF h<Min THENSI 
Min-h^i 
NrM%=n%SI 
Nr2%=Nr%SI 
END IFSI 

h. r=PatternHX (n%) *Colour (Nr%, 1) + (1-PatternHX (n%) ) *Colour (Nrl%, 1) SI 
h.g=PatternHX(n%) *Colour (Nr%, 2) + (1-PatternHX (n%) ) *Colour (Nrl%, 2) SI 
h.b-PatternHX(n%) *Colour (Nr%, 3) + (1-PatternHX (n%) ) *Colour (Nrl%, 3) SI 
h= (Bright .r-h. r) A 2 + (Bright .g-h.g) A 2 + (Bright .b-h.b) A 2SI 
IF h<Min THENSI 
Min=hSI 
NrM%=-n%SI 
Nr2%-Nr%SI 
END IFSI 
END IFSI 
NEXT Nr%SI 
NEXT n%SI 
SI 

IF NrM%<0 THENSI 
NrM%— NrM%SI 
SWAP Nrl%,Nr2%SI 
END IFSI 
SI 

CALL SetAPen& (RastPort&, CINT (Colour (Nrl%, 0) ) ) f 
CALL SetBPen& (RastPortS , CINT (Colour (Nr2% r 0) ) ) SI 
SI 

POKEL RastPort&+8, (PatternX&+NrM%*32) ' Address of PatternSSI 
POKE RastPort&+29,4SI 
SI 

CALL RectFill&(RastPort&,xl%,yl%,x2%,y2%)SI 
SI 

END SUBSI 
'SI 
'SI 

SUB ReProjection(xr,yr, zr,x,y, z) STATICf 
SHARED Sina, Sinb, Sine, Cosa, Cosb, Cose, Hx,Hy,Hz1 
* 2D->3DSI 



281 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



yl=y*Cosc-z*Sinc ' Rotation X-AxisSI 

zl=z*Cosc+y*SincSI 

x2=x*Cosb-zl*Sinb ' Rotation Y-AxisSI 

zr=zl*Cosb+x*Sinb+HzSI 

xr=x2*Cosa-yl*Sina+Hx ' Rotation Z-AxisSI 

y r=yl *Co sa+x2* Sina+HySI 
END SUBSI 
• err 

C ompu t epo i n t : SI 

' =>Compute Brightness of the point => stackSI 
StackPtr% - StackPtr% + 1SI 

CALL WhichBody (0,Px,Py, Pz,Rx,Ry,Rz, Original. ! , False) SI 
SI 

IF Body% > THENSI 

CALL SetBrightness (Body%,Px,Py,Pz, Mirror, Original ! ) SI 
Re st Lght ( St ackP t r% } =Mat (K (Body % , , 2 ) , 4 ) SI 
SI 

IF Bright <=0 THEN SI 
' unlit: SI 
Bright . r=Mat (K(Body%, 0,2) , 0) *Mat (K (Body%, 0, 2) ,3) SI 
Bright.g=Mat (K (Body %, 0,2) , l)*Mat (K (Body%, 0, 2) ,3) SI 
Bright .b-Mat (K (Body%, 0, 2) , 2) *Mat (K (Body%, 0, 2) , 3) 1 
ELSESI 

Kp%=Body%SI 

'Shadow ?SI 
CALL WhichBody (Kp%,Sx,Sy, Sz,Qx-Sx, Qy-Sy, Qz-Sz, False, True) SI 
SWAP Body%,Kp%SI 
IF Kp%>0 AND la<l THENSI 
1 in shadow: SI 
Bright. r=Mat (K (Body%, 0, 2) , 0) *Mat (K (Body%, 0, 2) , 3) f 
Bright.g-Mat (K (Body%, 0, 2) , 1 ) *Mat (K (Body%, 0, 2) , 3) SI 
Bright .b-Mat (K (Body%, 0, 2) , 2) *Mat (K (Body%, 0, 2) , 3) SI 
ELSESI 

' Mirror light source on interface: SI 
Bright-Bright* (1-P.estLght (StackPtr%) ) SI 
IF Bright<Mat (K (Body%, 0, 2) ,3) THENSI 

Bright=Mat (K (Body%, 0, 2) , 3) SI 
END IFSI 

Bright. r=Bright*Mat (K (Body%, 0,2) , 0) +Mirror*RestLght (StackPt r%) SI 
Bright .g=Bright*Mat (K (Body%, 0, 2) , 1 ) +Mirror*RestLght (StackPt r%) SI 
Bright .b=Bright*Mat (K (Body%, 0, 2) , 2) +Mirror*RestLght (StackPtr%) SI 
END IFSI 
END IFSI 
SI 

IF (RestLght (StackPtr%) >0) AND (StackPtr%<MaxStack%) THENSI 
' Determine Mirror interfaceSI 
1 Determine mirror vector to P-S:SI 
?. !je=Nx* (Px-Sx) +Ny* (Py-Sy)+Nz* (Pz-Sz)SI 
Rx=Sx-Px-f2*Dqe*NxSI 
Ry=Sy-Py+2*Dqe*NySI 
Rz-Sz-Pz + 2*Dqe*NzTi 
SI 

Stack ( St ackPtr%, 0) =Bright . rSI 
Stack (StackPtr%, 1 ) -Bright .gf 
Stack(StackPtr%,2)=Bright.bSI 
SI 

Px = SxSI 
Py = SySI 
Pz = SzSI. 
Original! = FalseSI 



282 



Abacus Appendix B — The Tracer Program 



GOSUB Computepoint ' Recursion I 11 If 

! 
Bright . r=Stack (StackPtr%, 0) +Stack (StackPtr%+l , 0) *RestLght (StackPtr%) ! 
Bright . g=Stack (StackPtr%, 1 ) +Stack (StackPt r%+l , 1 ) *RestLght (StackPt r% ) ! 
Bright.b=Stack(StackPtr%,2)+Stack(StackPtr%+l,2) *RestLght (StackPtr%)! 
END IF! 
ELSE! 

IF StackPtr% = THEN! 
Bright. r=-l! 
Bright.g=-1! 
Bright.b=-1! 
ELSE! 

Bright.r=0! 
Bright. g=0! 
Bright. b=0! 
END IF! 
END IF! 

Stack (StackPtr%, 0) =Bright . r! 
Stack (StackPtr%, 1) =Bright .g! 
Stack (StackPt r%, 2) =Bright.b! 
RestLght (StackPtr%)=0! 
StackPtr% = StackPtr%-l! 
RETURNf 



Shadows : ! 

1 Initialization 

Status$ = " Status: Shadows"+CHR$ (0) ! 

CALL SetWindowTitles& (NWBaseS, SADD (Status$) , 0) ! 
! 

GOSUB DeleteMenu! 

! 

Status$ = " Status: Init"+CHR$ (0) ! 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) ! 

GOSUB InitShadows! 
! 

Status$ - " Status: InitMinMax"+CHR$ (0) ! 

CALL SetWindowTitles& (NWBaseS, SADD (Status$) , 0) ! 

GOSUB InitMinMax! 
! 

Status$ = " Status: InitMinMaxLq"+CHR$ (0) ! 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) ! 

GOSUB InitMinmaxLq! 
! 

CALL Scron! 
! 

Status$ = " Status: Shadows M +CHR$ (0) ! 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) ! 
! 

XAOff = (BoxW% AND 1)*.5! 

YAOff = (BoxH% AND 1)*.5! 
! 

' Offsets to guarantee correct point size! 

IF XAOff = .5 THEN! 
XBOff = .5! 

ELSE! 

XBOff = 1! 

END IF! 

IF YAOff = .5 THEN! 
YBOff = .5! 



283 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



ELSEf 

YBOff = If 
END IFf 
f 

Body%=0f 
f 

FOR yb%=YStart%+BoxH%/2 TO Yend%+BoxH%/2 STEP BoxH%f 

FOR xb%=XStart%+BoxW%/2 TO XEnd%+BoxW%/2 STEP BoxW%f 

CALL ReProjection(Rx,Ry,Rz,0!,FN Xresc (xb%) , FN Yresc(yb%))f 
f 

Rx = Rx-Pxf 
Ry = Ry-Pyf 
Rz = Rz-Pzf 
f 

StackPtr% =-lf 
SI 

Pxl = Pxf 
Pyl = Pyf 
Pzl - Pzf 
f 

Original! = Truef 
GOSUB Computepointf 
f 

Px = Pxlf 
Py = Pylf 
Pz = Pzlf 
f 

IF Stack (0, 0) >=0 THEN 'If no Intersect point => -If 
Bright .r=Stack (0, 0) *Qh.rf 
Bright . g=St ack ( , 1 ) *Qh . gf 
Bright. b=Stack (0,2) *Qh.bf 

CALL OSSetPoint& (CLNG (xb%-BoxW%/2+XAOf f ) , CLNG (yb%- 
BoxH%/2+YAOf f) , CLNG (xb%+BoxW%/2-XBOf f ) , CLNG (yb%+BoxH%/2- 
YBOff) ,CLNG (1024*Bright.r) , CLNG (1024*Bright . g) , CLNG (1024*Bright .b) ) f 
END IFf 
NEXT xb%f 
f 

IF INKEY$ <> "" THENf 

IF yb% < Yend%+BoxH%/2 THENf 
f 

CALL Scrofff 

a$="Next line:"+STR$(yb%+BoxH%)f 
CALL Printlt (a$, 130, False) f 

CALL DialogBox ("Continue", 0, True, xla%, yla%, x2a%,y2a%, False) f 
CALL DialogBox("Stop", 2, False, xlb%, ylb%, x2b%,y2b%, False) f 
f 

CALL DoDialog(n%, 0,xla%,yla%, x2a%,y2a%, -1, -1,-1, -l,xlb%, ylb%, x2b%,y2b%) < 





CLSf 
IF n% = 
f 


THENf 




CALL 

ELSEf 

GOTO 

END IFf 


Scronf 
ShadowEndef 




END IF f 






END IFf 




f 


NEXT yb%f 





284 



Abacus 



Appendix B — The Tracer Program 



ShadowEnder'J 
f 

CALL Scrofffl 

CLS5 

GOSUB MakeMenu f 
RETURNS 

'END of SHADOWING. ASCII 
'SI 



285 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



The SERVICE.ASC module 



SERVICE. ASCI 

* 'SERVICE' - Module *f 

SI 

Saver: f 

' Save array K() to diskl 
GOSUB DirectorySI 
SI 

Status$ = " Status: Object Saver " + CHR$ (0) SI 
CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) 1 
SI 

LOCATE 3,1 SI 

PRINT " Under what name do you want the object saved?' 
PRINT SI 

PRINT " Filename : ";SI 
dn$ = ""SI 

CALL FormlnputSt ring (dn$,30!)SI 
SI 

CLSSI 

IF dn$<>"" THENSI 

dn$ = dn$ + ".LIST"SI 
OPEN "O",#l,dn$,1024SI 
PRINT #l,NumberKSI 
FOR n%=l TO NumberKSI 
FOR p%=0 TO 5SI 

PRINT #l,K(n%,p%,0),K(n%,p%, 1) ,K(n%,p%, 2) SI 
NEXT p%SI 
NEXT n%S[ 
CLOSE #1SI 
'The following will delete icons when included: SI 
■ dn$ = dn$+".info"SI 
KILL dn$SI 
END IFSI 
CLSSI 

GOSUB Make Menu SI 
RETURNSI 
'SI 
Loader: SI 

' Load array K() from diskSI 
GOSUB DirectorySI 
SI 

Status$ = " Status: Object Loader M +CHR$ (0) SI 
CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 
SI 

LOCATE 3,1 SI 

PRINT " Which object do you wish to load?"SI 
PRINT SI 

PRINT " Filename : ";SI 
dn$ = ""SI 

CALL FormlnputSt ring (dn$,30!)SI 
SI 

CLSSI 



286 



Abacus Appendix B — The Tracer Program 



IF dn$ <> "" THEN? 

dn$ = dn$ + " .LIST"? 

OPEN "I", #l,dn$, 1024*31 

INPUT #1, NumberK? 

LOCATE 10,10? 

PRINT "Total "; NumberK; " Object ("+dn$+") . "? 

PRINT? 

PRINT " Maximum number of objects? ";? 

MaxNumber = NumberK? 

CALL Fo rmlnpu 1 1 nt ( MaxNumber , 3 ! , 1 ! , Numbe rK) ? 



IF NumberK > MaxNumber THEN NumberK = MaxNumber <f 



ERASE K? 

DIM K (MaxNumber, 5, 2) ? 
? 

FOR n%=l TO NumberK? 
FOR p%=0 TO 5? 

INPUT #l,K(n%,p%,0),K(n%,p%,l),K(n%,p%,2)? 
NEXT p%? 
NEXT n%? 
CLOSE #1? 
Newone ! = True? 
Start% = 1? 
END IF? 
CLS? 

GOSUB MakeMenu? 
RETURN? 
! ? 
Merger: ? 

' Elements appended to available array K()? 
IF (MaxNumber-NumberK) <= THEN? 

Status$ - " Status: Object Merger"+CHR$ (0) ? 
CALL SetWindowTitlesfi (NWBase&, SADD (Status$) ,0)? 
? 

a$ = "Insufficient memory for more objects!!!"? 
CALL Print It (a$, 100, False) ? 

a$ = "Please select New to create a cleared array K() ! "? 
CALL Printlt (a$, 130, False) ? 

CALL DialogBox ("OK", 1, True, xla%, yla%, x2a%, y2a%, Fal se) ? 
? 

CALL DoDia log (n%,l,-l,-l,-l,-l,xla%,yla%,x2a%,y2a%, -1,-1, -1,-1)' 
ELSE ? 

GOSUB Directory? 
? 

Status$ = " Status: Object Merger"+CHR$ (0) ? 
CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0) ? 
? 

LOCATE 3,1? 

PRINT " Which object would you like to merge?"? 
PRINT? 
dn$ = "" ? 

PRINT " Filename : ";? 
CALL FormlnputString (dn$, 30 ! ) ? 
? 

CLS? 

IF dn$ <> "" THEN? 
dn$ - dn$ + ".LIST"? 
OPEN "I",#l,dn$,1024? 
INPUT #l,x? 



287 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



LOCATE 6, If 

PRINT " Total ";x;" Objects ("+dn$+") . "f 

PRINT f 

PRINT " Sufficent memory for ";MaxNumber-NumberK; " Objects 
PRINTf 

PRINT " How many merges? ";f 
num = xf 

CALL Formlnputlnt (num, 30 ! , 1 ! , 1000 ! ) f 
f 

IF x<num THEN num = xf 

IF MaxNumber-NumberK<num THEN num = MaxNumber-NumberKf 
f 

IF num>=l THENf 

FOR n%=NumberK+l TO NumberK+numf 
FOR p%=0 TO 5f 

INPUT #l,K(n%,p%,0) ,K(n%,p%,l) ,K(n%,p%,2)f 
NEXT p%f 
NEXT n%f 

NumberK = NumberK+numf 
Newone! = Truef 
Start% - If 
END IFf 
CLOSE #lf 
END IFf 
END IFf 
CLSf 

GOSUB MakeMenuf 
RETURNf 
'f 
Arraylnit : f 

1 Create new array K() f 

Status$ = " Status: New array creat ion"+CHR$ (0) f 
CALL SetWindowTitles& (NWBaseS, SADD (Status$) , 0) f 
f 
GOSUB DeleteMenuf 
f 

LOCATE 10, If 

PRINT " Maximum number of objects = ";f 
a = MaxNumberf 

CALL Formlnputlnt (a, 30 ! , ! , 1000 ! ) f 
f 
IF MaxNumber <> a THENf 
MaxNumber = af 
NumberK- Of 
ERASE Kf 

DIM K (MaxNumber, 5, 2) f 
Start% = Of 
END IFf 
f 

CLSf 

GOSUB MakeMenuf 
RETURNf 
'f 
'f 
LoadMat : f 

GOSUB Directoryf 

f 
Status$ = " Status: Material constants loader"+CHR$ (0) f 
CALL SetWindowTitles& (NWBaseS, SADD (Status$) , 0) f 



288 



Abacus Appendix B — The Tracer Program 



1 

LOCATE 3,11 

PRINT " Which material would you like to load?"1 
PRINT 1 

PRINT " Filename : ";1 
1 

dn$ = ""1 

CALL FormlnputSt ring (dn$,30!)1 
1 

IF dn$<> M " THEN 1 
dn$=dn$+".MAT"1 
OPEN "i",#l,dn$1 
matptr = 11 
INPUT #l,NumberMat1 
ERASE Mat 5 

DIM Mat (NumberMat, 6) 1 
WHILE NOT (EOF (l))*! 
FOR i=0 TO 61 

INPUT #1, Mat (matptr, i)1 
NEXT il 

matptr = matptr+11 
WEND1 
CLOSE #11 
END IF1 
CLS1 

GOSUB MakeMenul 
RETURN1 
'1 
'1 
ScreenSaver:1 

GOSUB Directoryl 

1 
Status$ = " Status: Screen saver"+CHR$ (0) 1 
CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0) 1 
1 

LOCATE 3,11 

PRINT " Under what name would you like the screen saved?"? 

PRINT 1 

PRINT " Filename : "; 1 

IFFFile$ = ""1 

CALL FormlnputString (IFFFile$ # 30 ! ) 1 

1 
IF IFFFile$ <> "" THEN1 
1 
Handles = ' File Handlel 
Buffers = ' Buffer memoryl 
1 reserve bufferl 

FlagsS = 65537s • MEMFJPUBLIC | MEMF_CLEAR1 
BufferSizeS = 3601 

Buffers = AllocMemS (BufferSizeS, FlagsS) 1 
IF Buffers = THENl 

Dialog$ = "No more memory! ! ! "1 
GOTO EndSavel 
END IF1 
1 

ColorBufferS = BufferSl 
1 

Nulls = 01 
PadByte% = Of 
1 



289 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



IF RasterW% = 320 THEM 
IF RasterH% = 200 THENSI 

Aspect % - SHAOBSI 
ELSESi 

Aspect! = SH14 0BSI 
END IFSi 
ELSESI 

IF RasterH% = 20 THENSI 

Aspect% - SH503SI 
ELSESI 

Aspect % = SHAOBSI 
END IFSi 
END IFSi 

IFFFile$ = IFFFiie$ + CER$(0)SI 
Handles = xOpenS (SADD (IFFFile$) , 1006) SI 
IF Handles = THENSI 

Dialog$ = "Can't open the file you wanted!!! 

GOTO EndSaveSI 
END IFSI 



1 How many bytes contain IFF-Chunks ?SI 

BMHDSizeS =■- 2 0S1 

CMAPSizeS = MaxColour%*3 + ( (MaxColour%*3) AND 1 ) SI 

CAMGSize& --= 4 SI 

BODYSize& = (RasterW%/ 8) *RasterH%*RasterT%SI 

1 FORMs ize& = Chunk-Length + 8 Bytes per Chunk-Header + 4 Bytes ("ILBM") C 

FORMS! zeS = BMHDS.izeS+CMAPSizeS+CAMGSizeS+BODYSizeS + 3 6SI 

• FORM-Header SI 

Chunk$ = "FORM 1 "]! 

Lengths - xWriteS (Handles, SADD (Chunk$) , 4 ) SI 

Lengths = xWriteS (Handles, VARPTR (FORMSizeS) , 4 ) SI 

' + ILBM for BitMap-FileSI 

Chunk$ - "ILBM" SI 

Lengths = xWriteS (Handles, SADD (Chunk$) , 4 ) SI 



IF Lengths <=■- T 

Dialog$ = "Writ 
GOTO EndSaveSI 
END IF SI 



HEN SI 

error on FORM-Header ! ! !' 



1 BMHD-Chunk SI 
Chunk$ - "BMHD"SI 
Lengths 



Lengths 
Lengths 
Lengths 
Lengths 
Temp% = 
Lengths 
Temp% - 
Lengths 
Temp% = 
Lengths 
Lengths 
Lengths 
Lengths 



= xWriteS 
= xWriteS 
= xWriteS 
= xWriteS 
= xWriteS 
(256 * Ra 
= xWriteS 


= xWriteS 
OSI 

= x'WriteS 
= xWriteS 
= xWriteS 
= xWriteS 



(Handles, SADD (Chunk$) , 4 ) SI 
( Handl e S , VARP TR (BMHDSi ze S ) , 4 ) S 
(Handles , VARPTR (RasterW%) ,2) SI 
( Handles, VARPTR (RasterH%) ,2) SI 
( Handl e 6 , VARPTR ( Nu 1 1 S ) , 4 ) SI 
sterT%) ' No MASKING^ 
(Handles, VARPTR (Temp%) ,2) SI 

1 No Packing^ 
(Handles, VARPTR (Temp%) ,2) SI 



(Handles, VARPTR (Temp%) ,2} SI 
(Handles , VARPTR (Aspect% ) , 2 ) 
(Handles, VARPTR (RasterW%) ,2 
( Handles, VARPTR (Raster H%) , 2 



290 



Abacus Appendix B — The Tracer Program 



IF Lengths <= THEN! 

Dialog$ = "Write error on BMHD-Chunk !!!"1 

GOTO EndSavel 
END IF 1 

' CMAP -Chunk 1 

Chunk$ = "CMAP"1 

Lengths = xWriteS (Handles, SADD (Chunk$) , 4) 1 

Lengths = xWriteS (Handles, VARPTR (CMAPSizeS) , 4 ) 1 

FOR i%=0 TO MaxColour%-11 

Colours% = GetRGB4% (ColorMapS , i%) 1 

blue = Colours% AND 151 

Colours% = Colours% - bluel 

green = (Colours%/16) AND 151 

Colours% = Colour s%-green*l 61 

red = (Colours%/256) AND 151 

POKE (ColorBuf ferS+ (i%*3) ) , red*161 

POKE (ColorBuf fers+ (i%*3)+l) ,green*16 1 

POKE (ColorBuf ferS+ (i%*3)+2) ,blue*161 
NEXT1 

Lengths = xWriteS (Handles, ColorBuf ferS , CMAPSizeS ) 1 

IF Lengths <= THENl 

Dialog$ - "Write error on CMAP-Chunk !!!"1 

GOTO EndSavel 
END IF 1 

' CAMG -Chunk 1 

Chunk$ = "CAMG"1 

Lengths = xWriteS (Handles, SADD (Chunk$) , 4) 1 

Lengths - xWriteS (Handles, VARPTR (CAMGSizeS) , 4 ) 1 

ModesS = PEEKW (Viewports + 32)1 

Lengths = xWriteS (Handles , VARPTR (ModesS) , 4) 1 

IF Lengths <= THENl 

Dialog$ = "Write error on CAMG-Chunk !!!"1 
GOTO EndSavel 
END IF 1 
1 

' BODY-Chunk (BitMaps)l 
Chunk$ = "B0DY"1 

Lengths = xWriteS (Handles, SADD (Chunk$) , 4) 1 
Lengths = xWriteS (Handles, VARPTR (BODYSizeS) , 4 ) 1 
BytesPerRow% = RasterW%/81 
FOR yl = TO RasterH%-11 
FOR b=0 TO RasterT%-11 

AdressS = BitPlanesS (b) + (yl*BytesPerRow%) 1 
Lengths = xWriteS (Handles, AdressS, BytesPerRow%) 
IF Lengths <= THENl 

Dialog$ = "Write error on BODY-Chunk ! ! ! "1 
GOTO EndSavel 
END IF 1 
NEXT1 
NEXT1 
1 

Dialog$ = "Saving OK"1 

EndSave:1 



291 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



IF Handles <> THEN CALL xCloseS (Handles ) SI 
IF Buffers <> THEN CALL FreeMemS (Buffers, Buf fer Sizes) SI 
CALL DialogBox (Dialog$,l, True, xlb%,ylb%, x2b%>y2b%, False) SI 
CALL DoDialog (n%, 1,-1,-1, -1, -1, xlb%, ylb%, x2b%, y2b%, -1, -1,-1,-1) 
END IFSI 
CLS SI 

GOSUB MakeMenuSI 
RETURNS 
'5 
'SI 
ScreenLoader : SI 

GOSUB Directory^ 
SI 
Status$ = " Status: Screen Loader"+CHR$ (0) fl 
CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0) f 
SI 

LOCATE 3,1 SI 

PRINT " Which IFF-File would you like to load?"SI 
PRINT SI 

PRINT " Filename : M ;SI 
IFFFile$ = ,,n SI 
CALL FormlnputString (IFFFile$, 30 ! ) SI 

SI 
IF IFFFile$ <> "" THENSI 



BMHD 


= False Tl 


CMAP 


= False! 


CAMG 


= FalseSI 


Body 


= FalseSI 


Handl 


es = OSI 


Buffe 


rs = OSI 



' reserve bufferSI 

FlagsS = 65537S ' MEMF_ PUBLIC | MEMF_CLEARSI 

BufferSizeS = 360SI 

Buffers = AIlocMemS (BufferSizeS, FlagsS) SI 

IF Buffers = THENSI 

Dialog$ = "No more memory!!! "SI 

GOTO EndLoadSI 
END IFSI 

InputBufferS = BufferSSI 
ColorBufferS = Buffers + 120SI 



IFFFile$ = IFFFile$ + CHR$(0)SI 
Handles = xOpenS (SADD (IFFFile$) , 1005) SI 
IF Handles = THENSI 

Dialog$ = "IFF-File can not be opened!!!' 

GOTO EndLoadSI 
END IFSI 



Lengths = xReadS (Handles, InputBufferS, 12) SI 

Chunk $ = ""SI 

FOR n% = 8 TO 11SI 

Chunk$ = Chunk$ + CHR$ (PEEK (InputBuf ferS+n%) ) ( 
NEXT SI 



292 



Abacus Appendix B — The Tracer Program 



IF Chunk$ <> "ILBM" THEN SI 

Dialog? = "Not IFF-Format ! ! ! "1 

GOTO EndLoadl 
END IF1 

ReadLoop:1 

Lengths = xReadS (Handles, InputBufferS, 8) SI 
ChunkwinlenS = PEEKL (InputBuf ferS + 4)1 
Chunk $ - ""1 
FOR n% = TO 31 

Chunk$ = Chunk$ + CHR$ (PEEK (InputBuf fers+n%) ) 1 
NEXT 1 
1 
IF Chunk$ = "BMHD" THEN ' BitMap-Header 1 

BMHD = Truel 

Lengths = xReadS (Handles , InputBuf ferS, ChunkwinlenS) 1 

RDepth% = PEEK ( InputBuf ferS + 8) 1 

Compression 5 * = PEEK (InputBuf ferS + 10)1 

RWidth% = PEEKW( Input Buffers +16)1 

RHeight% = PEEKW (InputBuf ferS + 18)1 

BytesPerRow% = RWidth%/81 

RMaxColors% = 2 A (RDepth%) 1 

1 IFF-Picture adapted to Display-Screen ?1 

IF (RWidth% <> RasterW%) OR (RHeight% <> RasterH%) THEN1 

Dialog$ = "Format error: "+STR$ (RWidth%) +" x"+STR$ (RHeight %) < 

GOTO EndLoadl 
END IF1 

ELSEIF Chunk$ = "CMAP" THEN ' Color-Palettel 

Lengths = xReadS (Handles , ColorBuf ferS, ChunkwinlenS ) 1 

CMAP = Truel 

' Color-Palette set upl 

FOR n% - TO RMaxColors% - 11 

red% = PEEK (ColorBuf ferS+ (n%*3) )/161 

green% = PEEK (ColorBuf ferS+ (n%*3) +1) /161 

blue% = PEEK(ColorBufferS+(n%*3)+2)/161 

dummy = SetRGB4 (Viewports, n%, red%,green%, blue%) 1 
1 

POKEW OSColour&+n%*8+2, red%/15*10241 

POKEW OSColourS+n%*8+4,green%/15*10241 

POKEW OSColourS+n%*8+6,blue%/15* 10241 
NEXT1 

ELSEIF Chunk$ = "BODY" THEN 'BitMap Loaderl 
CALL Scronl 
Body = Truel 

IF Compression% = THEN 'No compressionl 
FOR yl = TO RHeight% -11 
FOR b = TO RDepth% -11 
IF b<RasterT% THENl 

AdressS = BitPlanesS (b) + (yl*BytesPerRow%) 1 
ELSE1 

AdressS = Buffersl 
END IF1 

Lengths = xReadS (Handles, AdressS, BytesPerRow%) 1 
NEXT1 
NEXT1 

ELSEIF Compressionl = 1 THEN 'CmpByteRunl compressionl 



293 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



FOR yl = TO RHeight% -If 
FOR b = TO RDepth% -If 
IF b<RasterT% THENf 

AdressS = BitPlanesS (b) + (yl*BytesPerRow%) f 
ELSEf 

AdressS = Buffer&f 
END IFf 
NumBytes% = Of 

f 
WHILE (NumBytes% < BytesPerRow%) f 

Lengths = xReadS (Handles, InputBufferS, 1) f 

Code% = PEEK (InputBufferS )f 

IF Code% < 128 THEN ' Code%-Bytes take overf 

Lengths = xRead& (Handles, Adress& + NumBytes%, Code%+l) c 
NumBytes% = NumBytes% + Code% + If 
ELSEIF Code% > 128 THEN • Byte replicatesf 
Lengths = xReadS (Handles, InputBufferS, 1) f 
Byte% = PEEK (InputBufferS) f 
FOR n% = NumBytes% TO NumBytes% + 257 - Code%f 

POKE (Adresss+n%) , Byte%f 
NEXT f 

NumBytes% = NumBytes% + 257 - Code%f 
END IFf 
WENDf 
NEXTf 
NEXTf 

f 
ELSEf 

Dialog$ = "Unknown compression procedure !!! "f 
GOTO EndLoadf 
END IFf 
CALL Scrofff 
ELSE f 

1 "Unknown" Chunk-Typf 
FOR n = 1 TO Chunkwinlen&Tl 

Lengths = xReadS (Handles, InputBuf ferS, 1) f 
NEXTf 

1 Chunks have even numnber of bytesf 
IF (ChunkwinlenS AND 1) = 1 THEN f 

Lengths = xReadS (Handles, InputBuf ferS, 1) f 
END IFf 
END IFf 

1 All Chunks read?f 

IF (BMHD = True) AND (CMAP = True) AND (Body = True) THENf 

GOTO LoadOKf 
END IFf 

1 Read ok, get next Chunkf 

IF Lengths > THEN GOTO ReadLoopf 

IF Lengths < THEN 1 

Dialog$ = "Read error! ! ! "f 

GOTO EndLoadf 
END IF f 
f 
IF (BMHD=False) OR (CMAP=False) OR (Body=0) THENf 

Dialog$ = "Not all necessary ILBM-Chunks found! !!"f 

GOTO EndLoadf 
END IFf 



294 



Abacus Appendix B — The Tracer Program 



SI 

LoadOK:SI 

DialogS = "Loading OK"SI 
SI 

EndLoad : SI 

IF Handles <> THEN CALL xCloseS (Handles) SI 
IF Buffers <> THEN CALL FreeMemS (Buffers , BufferSizeS ) SI 
CALL Di al ogBox( Dial og$,l, True, xlb%,ylb%,x2b%,y2b%, False) SI 
CALL DoDialog(n%,l,-l,-l,-l,-l,xlb%,ylb%,x2b%,y2b%, -1,-1, -1,-1) 
END IFSI 
CLSSI 

GOSUB MakeMenuSI 
RETURN! 



HardCopy : SI 

Status$ = " Status: Screen hardcopy" + CHR$ (0) SI 
CALL SetWindowTitlesS (NWBaseS, SADD (Status$) , 0) SI 
SI 

GOSUB DeleteMenuSI 
SI 

CALL DialogBox ("No Printer", 0, True, xla%,yla%, x2a%,y2a%, False) SI 

CALL DialogBox ("Printer OK", 2,False,xlc%, ylc%, x2c%, y2c%, False) SI 

CALL DoDialog (n%, 0, xla%, yla%, x2a%, ya2%, -1, -1 , -1, -1, xlc%,ylc%, x2c%,y2c%) SI 

CLSSI 

IF n% <> THENSI 

Modes% - PEEKW (Viewports + 32) SI 
SI 

sigBit% = Alloc.Signal% (-l)SI 

FlagsS = 65537s ' MEMF PUBLIC | MEMF_CLEARSI 

MsgPortS = AllocMemS (40, FlagsS) SI 

IF MsgPortS = THENSI 

Dialog$ = "No ' MsgPort ' ! ! ! "SI 
GOTO EndPrinter4f 
END IFSI 
SI 

POKE (MsgPortS + 8) , 4 SI 

POKE (MsgPortS + 9), SI 

Nam$ = "PrtPort"+CHR$(0)SI 

POKEL (MsgPortS + 10), SADD (Najn$) SI 

POKE (MsgPortS + 14), SI 

POKE (MsgPortS + 15), sigBit%SI 

SigTaskS = FindTaskS (0) SI 

POKEL (MsgPortS + 16), SigTasksSI 



CALL AddPort (MsgPortS) 'lsit PortSI 

i ©Requests - AllocMemS ( 64 , FlagsS) SI 
IF ioRequestS = THENSI 

Dialog$ - "No ioRequest ! ! ! "SI 

GOTO EndPrinter3SI 
END IFSI 

POKE(ioRequest& + 8), 5 SI 
POKE (ioRequestS + 9) , SI 
POKEL (ioRequest S + 14), MsgPort SSI 



Nam$ - "printer. device"+CHR$ (0) SI 

PrinterErrorS - OpenDeviceS (SADD (Nam$) , 0, ioRequestS, 0) SI 



295 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



IF PrinterError& <> THENf 
Dialog$ = "No Printer ?l?"f 

GOTO EndPrinter2f 
END IF<J 



POKEW (ioRequestS 
POKEL (ioRequest& 
POKEL (ioRequest& 
POKEL (ioRequest& 
POKEW(ioRequest& 
POKEW (ioRequest& 
POKEW (ioRequest& 
POKEW (ioRequest& 
P OKEL ( i oReque s t & 
POKEL (ioReque st & 
POKEW (ioRequest& 



28), 


11 


32), 


RastPort& 


36), 


ColorMap&f 


40) , 


Modes %f 


44), 


Of 


46), 


Of 


48), 


RasterW%f 


50), 


RasterH%f 


52), 


O&f 


56), 


O&f 


60), 


&H84f 



DumpRastport to Printer^ 
Print entire screen f 



CALL DialogBox( "Printing. . . ", 1, False, xla%, yla%,x2a%, y2a%, False) 

PrinterErrorS = DoIO& (ioRequest&) f 
IF PrinterError& <> THEN^I 

D.ialog$ = "DumpRPort Error ="+STR$ (PrinterError&) +" ! ! ! "f 

GOTO EndPrinter<5 
END IFfl 

CLSf 

Dialog$ = "Hardcopy done"ST 

EndPr inter: f 

CALL CloseDevice(ioRequest&)5 

EndPrinter2: f 

POKE(ioRequest& + 8), &HFF1 
POKEL (ioRequest& + 20), -If 
POKEL (ioRequestfi + 24), -If 
CALL FreeMem& (ioRequest&, 64) f 



EndPrinter3:<II 

CALL RemPort (MsgPort&) f 
POKE(MsgPort& + 8), &HFF f 
POKEL (MsgPortS + 20), -If 
CALL FreeSignal (sigBit%)1 
CALL FreeMem& (MsgPort&, 40) f 
f 

EndPrinter4:f 

CALL DialogBox (Dialog$, 1, True, xlb%, ylb%,x2b%, y2b%, False) f 
CALL DoDialog(n%, 1, -1 , -1, -1, -1, xlb%, ylb%, x2b%, y2b%, -1 , -1, -1 , - 
END IF1 
CLSf 

GOSUB MakeMenu f 
RETURNS 



1) SI 



LoadEditor:<2 

Status$ = " Status: Editor loading"+CHR$ (0) f 
CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) f 

f 

GOSUB DeleteMenuf 

f 

CALL DialogBox ("Cancel, 0, True,xla%,yla%,x2a%,y2a%, False) 
CALL DialogBox ("Load", 2, False, xlc%, ylc%,x2c%, y2c%, False) c 



296 



Abacus Appendix B — The Tracer Program 



CALL DoDialog (n%, 0, xla%, yla%, x2a%, ya2%, -1, -1,-1, -1, xlc%, ylc%, x2c% , y2c%) 

CLSSI 

IF n% = 2 THENSI 

CHDIR "Tracer: " SI 
GOSUB CloseltSI 
CHAIN "Edit or" SI 

END IFSI 

GOSUB MakcMenu SI 
ENDSI 

SI 
CiearScreen:SI 

Status$ = " Status: Clear screen"+CHR$ (0) SI 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 

SI 

CALL SetRastS (RastPortS, 0) SI 

Hg = TrueSI 

SI 

GOSUB NOOPSI 
RE TURN SI 
'SI 
'SI 
Info: SI 

' Information about free elements of K()SI 

Status$ = " Status: Info"+CHR$ (0) 1 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 
SI 

GOSUB DeleteMenuSI 
SI 

CALL PrintIt("3D - CAD" , 60, False) SI 

CALL Printlt ("Original-Version: Peter Schulz (c) 1 986", 75, False) SI 

CALL Printlt ("Amiga-Version: Bruno Jennrich (c) 1987" , 90, False) SI 
\ 

a$ = "Maximum number of objects : " + STR$ (MaxNumber) SI 

CALL Printlt (a$, 105, False) SI 
SI 

a$ = "Actual number of objects : " + STR$ (NumberK) SI 

CALL Printlt (a$, 120, False) SI 
SI 

GOSUB PauseSI 
SI 

CLSSI 

GOSUB MakeMenuSI 
RE TURN SI 
'SI 
Help: SI 

1 Which key press for which actionSI 

Status$ = " Status: Help" + CHR$ (0) SI 

CALL SetWindowTitles& (NWBase&, SADD (Status$) , 0) SI 
SI 

GOSUB DeleteMenuSI 
SI 

LOCATE 2,1SI 
SI 

PRINT " P rojection point "fl 

PRINT " H Main point"SI 
SI 

PRINT " W enter angle" 5 

PRINT " Cursor keys => rotate"SI 

PRINT " R otate (SHIFT, CONTROL) "SI 



297 



Appendix B — The Tracer Program 



Amiga 3D Graphic Programming 



PRINT " D: spacing for main point M< I[ 
PRINT " +1-1*1/ Enlarge/ reduce spacing (SHIFTS- 
PRINT " V Enlarged 

PRINT " L oad Object "SI 

PRINT " S ave Object "SI 

PRINT " M erge Object "5 

PRINT " N ew, clear all objects"^ 

PRINT " B Screen saver"SI 

PRINT " Q => Prograjn end (Quit)" SI 



PRINT 



Fl => Editor load" 



PRINT " F9 => Shadows initialization'^ 
PRINT " FiO => Shadows'^ 
PRINT " <SPACE> => Show picture "SI 
PRINT " C lear screen"; SI 
SI 

GOSUB PauseSI 
CLSSI 

GOSUB MakeMenuSI 
RETURNS 
'SI 
'SI 

SUB Sky (a%,Col%,num%) STATICSI 

SHARED WScreen&,NWBase&,RasterW%,RasterH%,RasterWl%SI 
SHARED RasterHl%, RasterW2%, RasterH2%, RastPort&SI 
CALL ScronSI 

SI 
CALL SetAPenS (RastPort &, Col%) SI 
CALL SetRastS (RastPortS, 0)SI 
SI 

FOR n%=l TO num%SI 
RANDOMIZE TIMERS! 
SI 

IF a%<4 THENSI 

IF a% AND 1 THENSI 

x%=RasterW2%+RasterW2%*RND*RND*SGN(RND-.5)SI 
y%=RasterH2%+RasterH2%*RND*RND*SGN(RND-.5)S[ 
ELSESI 

x%=RND*RasterWl%SI 
y%=RND*RasterHl%SI 
END IFSI 



IF a% AND 2 THENSI 

IF x%=RasterW2% AND y%=RasterH2% THENSI 
dummy = WritePixel (RastPorts, x%,y%) SI 
ELSESI 

xl%=(x%-RasterW2%)*.l+x%SI 
yl%=(y%-RasterH2%)*.l+y%SI 
IF xl%>=0 AND xl%<RasterW% AND yl%>=0 
CALL Move& (RastPort&,x%,y%)SI 
CALL Draws (RastPortS, xl%, yl%) SI 
END IFSI 
END IFSI 
ELSESI 



AND yl%<RasterH% THENSI 



IF RND<.9 THENSI 

CALL WritePixelS (RastPort&,x%,y%) 



298 



Abacus Appendix B — The Tracer Program 



ELSE<5 

CALL Moves (RastPortS,x%-l,y%) SI 
CALL Draws (RastPortS,x%+l,y%) SI 
CALL Draws (RastPortS, x%,y%-l) SI 
CALL Draws (RastPortS, x%, y%+l) SI 
END IFSE 
END IFSI 
ELSESI 
SI 

x%=RND*RasterWl %SI 
y%=RND*RasterHl %SI 

CALL Moves (RastPortS, RasterW2%, RasterH2%) f 
CALL Draws (RastPortS, x%,y%) SI 
END IFSI 
NEXT n%SI 

CALL SetAPenS (RastPortS, 1) SI 
SI 

CALL Scroff SI 
END SUBSI 
'SI 

SUB Fhg(Coloursl%,Colours2%) STATICSI 

SHARED RasterWl%, RasterHl%, Colour () / MaxColour% / WScreensSI 
SHARED NWBaseS , RastPortS , OSSetPointS , OSModusS , OSMaxColourS SI 

1 Produce floating passage between Coloursl and Colours2SI 

CALL ScronSI 
\ 

red. s=Colour (Coloursl%+l, 1) SI 

green. s=Colour (Coloursl%+l, 2) SI 

blue . s=Colour (Coloursl%+l, 3) \ 

red.e=Colour (Colours2%+l, 1) SI 

green. e=Colour (Colours2%+l ,2)1 

blue.e=Colour (Colours2%+l, 3) SI 



SI 



IF (PEEKW (OSModusS) AND SH800) = SH800 THEN ' HAM SI 
'Background limited to 16 Colors, or else Objects disturbed. SI 



POKEW OSMaxColourS, 16SI 
FOR y%=0 TO RasterHl%SI 

red=red.s+(y%/RasterHl%) * (red. e-red. s) SI 
green=green. s+ (y%/RasterHl%) * (green. e-green. s) SI 
blue=blue.s+(y%/RasterHl%) * (blue.e-blue. s) SI 

CALL SetPoint (0,y%,RasterWl%,y%, red, green, blue) SI 
CALL 
OSSetPointS (0,y%, RasterWl%, y%,CLNG (1024*red) , CLNG (1024*green) , CLNG (1024*blue) ) c 
NEXT y%SI 

POKEW OSMaxColourS, 64SI 
ELSESI 

FOR y%=0 TO RasterHl%SI 

red=red.s+ (y%/RasterHl%) * (red. e-red. s) SI 
green=green. s+ (y%/RasterHl%) * (green. e-green. s) SI 
blue=blue.s+(y%/RasterHl%) * (blue.e-blue. s) SI 
' CALL SetPoint (0, y%, RasterWl%, y%, red, green, blue) SI 

CALL 
OSSetPointS (0, y%, RasterWl%, y%, CLNG (1024 *red) , CLNG (102 4 *green) , CLNG (1024 *blue) ) c 
NEXT y%SI 
END IFSI 
CALL ScroffSI 
END SUBSI 



299 



Appendix B — The Tracer Program Amiga 3D Graphic Programming 



Background: fl 

1 Background Determined 

Status$ = " Status: Background selection"+CHR$ (0) f 
CALL SetWindowTitles& (NWBase&, 5ADD (Status$) , 0) f 
SI 

GOSUB DeleteMenuSI 
SI 

CALL DialogBox("Pattern",0,True,xla%,yla%,x2a%,y2a%, False) SI 
CALL DialogBox ("Load screen", 2, False, xlb%,ylb%,x2b%,y2b%, False) SI 
SI 

CALL DoDialog(n%,0,xla%,yla%,x2a%,y2a%,-l,-l,-l,-l,xlb%,ylb%,x2b%,y2b%)SI 
CLS SI 
SI 

IF n%=2 THENSl 

GOSUB ScreenLoaderf 
Hg = TrueSI 
ELSESI 

CALL DialogBox ("Pattern", 0, True, xla%, yla%,x2a%, y2a%, False ) SI 
CALL DialogBox ("Sky" , 1 , False, xlb%, ylb%, x2b%, y2b%, False) 1 
CALL DialogBox ("Floating", 2, False, xlc%,ylc%,x2c%,y2c%, False) SI 
1 

CALL DoDialog(n%, 0, xla%,yla%, x2a%, y2a%, xlb%, ylb%, x2b%, y2b%, xlc%, ylc%, x2c%, y2c%) 
SI 

CLSSI 
SI 

IF n% = THEN SI 
SI 

CALL Printlt ("Background = Pattern", 40, False) SI 
SI 

LOCATE 10,1 SI 

PRINT " Number of the pattern (0..34) : ";fl 
a - Of 

CALL Formlnputlnt (Hx, 30 ! , ! , 34 ! ) SI 
Xpattern% = afl 
f 

LOCATE 11,1 SI 

PRINT " Foreground pen (APen) : ";SI 

a=APen%SI 

CALL Formlnputlnt (a, 30 ! , ! , CSNG (MaxColour%-l) ) SI 

APen% = aSI 
SI 

LOCATE 12,1 SI 

PRINT " Background pen (BPen) : ";SI 

a = BPen%SI 

CALL Formlnputlnt (a, 30 ! , ! , CSNG (MaxColour%-l) ) SI 

BPen% - aSI 
SI 

Xpattern% = Xpattern% MOD (NumberPatternS%+NiimberPatternX%*2 + l ) SI 
SI 

IF Xpattern% > NumberPatternS% THENSI 

CALL ExtendedFill (0, 0, RasterWl%, RasterHl%, PatternHX (Xpattern%- 
NumberPatternS%) , 0! , 1! , APen%,BPen%) SI 
ELSESI 
CALL StandardFill (0, 0, RasterWl%, RasterHl%, PatternHS (NumberPatternS%- 
Xpattern%) , APen%, BPen%) SI 

END IFSI 

CLSSI 

Hg = TrueSI 
END IFSI 



300 



Abacus Appendix B — The Tracer Program 



IF n% = 1 THENf 

LOCATE 3, If 

PRINT " Sky type:"f 

PRINT " = Stars (scattered) "5 

PRINT " 1 = Stars (centered) "f 

PRINT " 2 = Lines (scattered) "f 

PRINT " 3 = Lines (centered) "SI 

PRINT " 4 = Lines (middle centered) " f 

f 

LOCATE 10, If 

PRINT " Type : ";f 

a = Art%f 

CALL Formlnputlnt (a, 30 ! , ! , 4 ! ) f 

Art% = af 
f 

LOCATE 11, If 

PRINT " Color : ";f 

a = If 

CALL Formlnputlnt (a, 30 ! , ! , CSNG (MaxColour%-l) ) f 

HColr% = af 
f 

LOCATE 12, If 

PRINT " Number : ";f 

a = lOOf 

CALL Formlnputlnt (a, 30 ! , 0! , 500! ) f 

num% = af 
f 

CLSf 

CALL Sky (Art%, HColr%, num%) f 

Hg = Truef 
END IFf 
f 
IF n% = 2 THENf 

CLSf 
f 

CALL Printlt ("Floating Background", 40, False) f 

f 

LOCATE 10, If 

PRINT " from color: ";f 

Fl = Of 

CALL Formlnput (Fl , 30 ! , ! , CSNG (MaxColour%-l ) ) f 

Coloursl%=Flf 

LOCATE 12, If 

PRINT " to color: ";f 

F2 = If 

CALL Formlnput (F2, 30 ! , ! , CSNG (MaxColour%-l ) ) f 

Colours2%=F2f 
f 

CALL Fhg(Coloursl%,Colours2%)f 

Hg = Truef 
END IFf 
END IFf 
CLS f 

GOSUB MakeMenuf 
RETURNf 



301 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



The Editor Program 



The following is the complete listing of the editor program found on 
the optional diskette. The example program that follows contain some 
BASIC lines that must be entered on one line in AmigaBASIC even 
though they appear on two lines in this book. Formatting the program 
listings to fit into this book has caused some long BASIC lines to be 
split into two lines. To show where a BASIC line is actually ended, an 
end of paragraph character (%) will be used. This is not to be entered, it 
only shows when the <Return> key should be pressed in the BASIC 
editor. For example, the following line is split into two lines in this 
book but must be entered as one line in AmigaBASIC: 

WinDef NWindow, 100, 50, 460, 150, 32+64+512&, 15&+4096&, 
0&, Title$1 

The H shows the actual end of the BASIC line. 

The following pages contain the complete listing of the editor program 
contained on the optional diskette. 



302 



Abacus Appendix C — The Editor Program 



'** RAY- TRACING -ED I TOR **<£ 

I ****************x****-*****C! 
SI 

GOSUB init 'Initialization all variables and screen configurations! 
WHILE quit=0 'wait until end is signaled by quit =11 

a$=INKEY$5 

IF a$><"" THENSI 

GOSUB shortcuts 'Get a key and compare with shortcut si 

END IF SI 
WENDS! 

GOSUB ende 'Program endSI 
ENDSI 
SI 

« *******x*****************CT 

' ** INITIALIZATION **SI 

i *****••*****•***•*•**•*** cjt 

SI 

init:SI 

DIM gadget s% (400) ,gadget% (10, 7) SI 

FOR i=0 TO 10 'Clear all gadgets (see below) SI 

gadget %(i, 0)=~1SI 
NEXT i SI 

nrl%=0 'global gadget pointer to elements usedSI 
nr2%=0SI 
nr3%=0SI 
nr4%-0SI 
nr5%-QSI 
nr6%=--0Sl 

LOCATE 2,1 'Read graphic information of gadgets usedSI 
PRINT " NO "SI 
LINE (5,5)-(65,20),,bSI 
GET (5, 5) -(65, 20) , gadgets% (200) SI 
LOCATE 2,1 SI 

PRINT " YES " SI 

LINE (5,5)-(45,20),,bSI 
GET (5,5)~(45,20),gadgets%(100) SI 
LOCATE 2, 1SI 
PRINT " OK "SI 
LINE (5,5)- (35,20) , ,bSl 
GET (5,5)- (35,20) , gadget s% (0) SI 
CLSSI 

DEFINT a-zSI 
FOR i-44 TO 122 SI 

iegchar$--legchar$+CHR$ (i) 'legal characters for text entrySI 
NEXT i SI 

grad! =57. 29577 'Conversion constants - radian to degreeSI 
rad! = . 017453 'Conversion constants - degree to radianSI 
empty$=SPACE$ (2 9) 'Empty iineSI 

max ! =10000 'Upper and lower limits of real valuesSI 
min! =-max ! SI 

ptr^O 'Pointer to current list elementsSl 

matptr=0SI 

dir$="libs/" 'current directory^ 

OPEN dir$ + "maxnum" FOR INPUT AS 1 'maximum number in bodies and material list SI 
INPUT # 1 , k n urn , ma t n u mSI 
CLOSE 1SI 

col our =1 'character color l=white 3=orangeSl 

DIM t (1 I) , tabs (11, 1 ) , typ$ (24) , k! (knam,5,2) , mat ! (mat nam, 6) SI 
FOR i=l TO knum 'combine free listsSI 

k! (i,0,C)--lSI 



3 3 



Appendix C — The Editor Program 



Amiga 3D Graphic Programming 



arrange by type and name! 



k! (i,0,l)=i+l! 
NEXT i! 
FOR i=l TO matnum! 

mat! (i, 0) =-lSI 

mat! (i,l)=i + l! 
NEXT i ! 
typ$ (0) -"Plane" 
typ$ (1) -"Triangle"! 
typ$ (2) -"Parallelogram"! 
typ$ (3) -"Circle"! 
typ$ (4) -"Circle segment"! 
typ$ (5)="Arc"H 
typ$ (10) -"Sphere"! 
typ$ (20) -"Cylinder"! 
typ$ (21) -"Cylinder segment"! 
typ$ (22) -"Cone"! 
typ$ (24) -"Spheroid" ! 

t(l)=0 'Arrange by menu line and type! 
t(2)=l! 
t (3)-2! 
t(4)=3! 
t (5)=4! 
t(6)-5! 
t (7)=10! 
t (8) -20! 
t (9) =215 
t (10) =22! 
t(ll)=24! 
xcorrfac! -1 . 8£ 
maxlines-20 
pi2!=6. 283185 
factor! -1 
mx!=0 
my!=116! 
mz!-116! 
auit=0 



'Correction factor for the horizontal resolution! 

'Maximum number of lines available for circle drawing! 

■2*3.141592! 

'Sizing factor! 

'Position of upper left screen corner! 



'Initialize end flag! 



moy!=0! 

moz!=0! 

kf ree=l 

matf ree=i! 

rp&=WINDOW(8) 

cw%-PEEKW(rp&+60)! 

ch%=PEEKW(rp&f58)! 

File$="ob jects/" 'contains all Filenames, used by disk operations! 



Set free pointer to start of list! 
'Determine cursor width and height! 



DECLARE FUNCTION allocmemS LIBRARY 'addition of allocmem and f 
LIBRARY dir$+ "exec. library" 'alloc- and freemem added! 
LIBRARY dir$ + " intuit ion. library" 'set- and clearpointer added! 
LIBRARY dir$+"graphics . library" 'add the procedure setdrmd! 



reemem! 



SCREEN 1, 640,256,2,2! 

WINDOW 1,"XY-PLANE", (0, 0) - (298, 1 15) , 7, 1! 

WINDOW 2,"XZ-PLANE", (320, 0) - (617, 115) , 7, 1! 

WINDOW 3, "YZ-PLANE", (320 , 85) - (61 7, 190) , 7, 1! 

WINDOW 4, "RAY-TRACING-EDITOR", (0, 85) -(314, 190) ,22, 1! 

buffer&=allocmem& (68*2, 2) "Memory for mouse pointer^ 
CALL initmaus! 



CALL actlwith4 
CALL deactiv5 



'Menu 1 with 4 active! 
'Menu 5 deactivated! 



304 



Abacus Appendix C — The Editor Program 



MENU 0N5 

ON MENU GOSUB choice^ 

5 

MOUSE ON5 

ON MOUSE GOSUB clicks 

5 

PRINT"Body :0" 'Create input windowSI 

LOCATE 9,15 

PRINT" Seginent : 0, 116, 116"5 

PRINT"Mouse : 0, 0, 0"5 

PRINT "Factor: 1 Lines :20"5 

LINE (0, 7*ch%+2) - (39*8+3, 7*ch%+2) 5 
RETURN5 
5 

• ••••••••••••••••or 

'** EEND **5 

• ••••••••••••••• or 

5 
ende : 5 

MENU OFF 'Close window screen and libraries*!! 

MENU RESETS 

MOUSE OFF5 
5 

WINDOW CLOSE 25 

WINDOW CLOSE 35 

WINDOW CLOSE 45 

SCREEN CLOSE 15 

ON ERROR GOTO Problem5 

WINDOW l,"Call Tracer " ' AMIGABasic needs WINDOW 15 

Problem: ' this command checks errors 5 

' it is necessary5 

CALL freemem& (buffers, 68*2) 'Release memory again5 

LIBRARY CLOSE5 

CHAIN "tracer"5 
RE TURN 5 
5 
i •••••••••••••••••or 

'** SHORTCUTS **5 
i •••••••••••••••••or 

5 
shortcuts: 5 

a=ASC(a$) 'ASCII-Value of pressed key5 
MENU OFF 'Compare with valid keys5 
IF a=4 THEN5 

IF mat=0 THEN5 

CALL deleter (ptr) 'Delete List element5 
ELSE5 

CALL deletermat (matptr) 'Delete Materials 
END IF5 
END IF5 
IF a=42 AND mat=0 THEN5 

CALL factor2 (factor! ) ' factor=factor*25 
END IF5 
IF a=4 7 AND mat=0 THEN5 

CALL factorhalf (factor! ) " factor=f actor*0 . 55 
END IF5 
IF a=114 THEN5 
IF mat=0 THEN5 

CALL rights (ptr) 'go to right elements 
ELSE5 

CALL rightsmat (matptr) 5 



305 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



END IFSI 
END IFSI 
IF a=108 THENf 

IF mat=0 THENSI 

CALL lefts (ptr) 'go to left element^ 

ELSESI 

CALL leftsmat (matptr)f 

END IFSI 
END IFSI 
IF a=ll THENSI 

IF mat=0 THENSI 

CALL getelem(ptr) 'correct current element SI 

ELSESI 

CALL getmat (matptr) SI 

END IFSl 
END IF SI 
IF a=115 AND mat=0 THENSI 

CALL showandwait (ptr) 'show current element on output windowSI 
END IFSI 
IF a=18 AND mat=0 THENSI 

CALL refresh ' redraw screenSI 
END IFSI 
IF a=10 9 AND mat = l THENSI 

CALL mat input (matptr ) 'Material inputs 
END IF SI 
MENU ON SI 
RETURNS! 



< •••••••••••••••••••or 
* ** READ MENU **SI 

Si 
choice :SI 

MENU OFF 'select indivual menu items and subroutines* 
title=MENU (0)^1 
chose=MENU (1 ) SI 



IF title=l THEN 'Transformations 
IF chose-1 THENSI 

CALL rotation (ptr) SI 
END IFSI 
IF chose=2 THENSI 

CALL translation (ptr) SI 
END IFSI 
IF chose=3 THENSI 

CALL si zing (ptr) SI 
END IFSI 
IF chose=4 THENSI 

CALL copier (ptr) SI 
END IFSI 
IF chose=5 THENSI 

CALL deleter (ptr) SI 
END IF SI 
IF chose=6 THENSI 

CALL getelem(ptr)SI 
END IF SI 
END IFSI 



IF title=2 THEN 'BodySI 
CALL entry (ptr) SI 



306 



Abacus Appendix C — The Editor Program 



END im 

SI 

IF title=3 THEN 'Diskette operations^ 
IF chose=l THENSI 

CALL loadlistSI 
END IFSI 
IF chose=2 THENSI 

CALL loadmatSI 
END IFSI 
IF chose=3 THENSI 

CALL savelistSI 
END IFSI 
IF chose=4 THENSI 

CALL savematSI 
END IFSI 
END IF SI 
f 

IF title=4 THEN 'Operational 
IF chose=l THENSI 

CALL lefts (ptr) SI 
END IFSI 
IF chose=2 THENSI 

CALL rights (ptr)SI 
END IFSI 
IF chose=3 THENSI 

CALL liob(mx! , my ! ,mz ! ) SI 
END IFSI 
IF chose=4 THENSI 

CALL setf actor (factor! ) SI 
END IFSl 
IF chose=5 THENSI 

CALL f actor2 ( factor ! ) SI 
END IF SI 
IF chose=6 THENSI 

CALL factorhalf (factor! ) SI 
END IFSI 
IF chose=7 THENSI 

CALL mateddySI 
END IFSI 
IF chose=8 THENSI 

CALL refreshSI 
END IFSI 
IF chose=9 THENSI 

CALL showandwait (ptr) SI 
END IFSI 
IF chose=10 THENSI 

CALL se 1 1 i ne s ( maxl i ne s ) SI 
END IF SI 
IF chose=ll THENSI 

CALL finish (quit) SI 
END IFSI 
END IFSI 



IF title=5 THEN 'Material editorSI 
IF chose=l THENSI 

CALL leftsmat (matptr)SI 
END IFSI 
IF chose=2 THENSI 

CALL right smat (matptr) SI 
END IFSI 
IF chose=3 THENSI 



307 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



CALL deletermat (matptr) SI 
END IFSI 
IF chose=4 THENSI 

CALL getmat (matptr) SI 
END IFSI 
IF chose=5 THENSI 

CALL mat input (matptr) SI 
END IF SI 
IF chose=6 THENSI 

CALL finishmatf 
END IFSI 
END IFSI 
SI 

MENU ON SI 
RETURNSI 

SI 

i *********** *******gj 

'** READ MOUSE **SI 

« *************** ***Q[ 

SI 
click:SI 

dummy=MOUSE(0)SI 

x !=MOUSE (3) / (factor ! *xcorrfac! ) 'Get mouse position and computeSI 
y!=M0USE(4)/factor!SI 
n=WINDOW(0) 'window clickedSI 
oldwindow=WINDOW (1) 'output windowSI 
CALL activatewindow& (WINDOW (7) ) SI 
IF n<4 THEN 'was projection window clicked?SI 
WINDOW OUTPUT nSI 

LINE (MOUSE (3) -1, MOUSE (4) )- (MOUSE (3) +1, MOUSE (4 ) ) ,3 'Draw circle! 
LINE (MOUSE (3) , MOUSE (4) -1) - (MOUSE (3) .MOUSE (4) +1) , 3SI 
IF n=l THEN 'compute spatial coordinatesSI 
mox ! =mx ! +x ! SI 
moy ! =my ! -y ! SI 
ELSESI 

IF n=2 THENSI 
mox i =mx ! +x I SI 
moz! =mz! -y ! SI 
ELSE SI 

IF n=3 THENSI 
moy ! =my ! -x ! SI 
moz!=mz! -y ! SI 
END IFSI 
END IFSI 
END IFSI 

mox!=FIX(mox! + .5) ' roundSI 
moy!=FIX(moy! + .5) SI 
moz!=FIX(moz! + .5)SI 
WINDOW OUTPUT 4SI 

mo$=STR$ (mox! ) +", "+STR$ (moy! ) +", "+STR$ (moz ! ) SI 

LOCATE 10,8 'delete old mouse values and display new ones! 

PRINT SPACE$(26)SI 
LOCATE 10, 8 SI 
PRINT MID$(mo$,l,26) SI 
WINDOW OUTPUT oldwindowSI 
ELSESI 

CALL checkgadget 'was a gadget clicked?SI 
END IFSI 
RETURN SI 
SI 
SI 



308 



Abacus Appendix C — The Editor Program 



'** INPUT **! 

i ****** *******CT 
! 

SUB entry (ptr) STATIC! 
'TASK -.Read data for a new body! 
' PARAMETER: => ptr points to old body! 
' <= ptr points to specified body! 

SHARED k ! ( ) , t ( ) , chose! 
CALL newelem(ptr)! 
k! (ptr, 0,0) =t (chose) ! 
CALL showelem(ptr) ! 
CALL getelem(ptr)! 
IF k! (ptr, 5, 2) =1 THEN! 

CALL drawelem(ptr)! 
END IF ! 
END SUB! 
SI 

SUB getstring(old$,a$, z$, z, s, inplen) STATIC! 
TASK .-Reads two strings which can be edited from the input line! 
using cursor left/right, backspace and delete.! 
In addition the string scrolls when the input extends past! 
the screen line ! 
PARAMETER: =>old$ old value of string to be read! 
a$ key pressed ! 
z$ valid characters! 
z line! 
s column! 

inplen Length of input window! 
<=old$ specified string! 
IF inplen =1 THEN 'if only one char entered? => no Return! 
old$=a$! 
WHILE INSTR(z$,old$)=0! 

CALL getkey (old$,z, s)! 
WEND! 

LOCATE z,s! 
PRINT old$! 
ELSE! 

i=l 'points to current string position! 
positional 'points to current screen position! 
WHILE ASC(a$)><13! 

IF INSTR(z$,a$)><0 THEN 'valid character?! 

old$=LEFT$ (old$, i-1 ) +a$+RIGHT$ (old$, LEN (old$) -i + 1) ! 

i-i+1! 

posit ion=position+l! 

IF position>inplen THEN! 

position=inplen ! 
END IF ! 
ELSE ! 

IF ASC(a$)=30 AND i<=LEN(old$) THEN 'Cursor right?! 
i=i+l! 

posit ion=position+l! 
IF position>inplen THEN! 

position=inplen ! 
END IF ! 
ELSE! 

IF ASC(a$)=31 AND i>l THEN 'Cursor left?! 
i=i-l! 

posit ion=position-l! 
IF position-0 THEN! 

positional! 
END IF ! 



309 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



ELSE SI 

IF ASC(a$)=127 AND i<=LEN(old$) THEN 'delete ?SI 
old$=LEFT$ (old$, i-1) +RIGHT$ (old$, LEN (old$) -i ) SI 
ELSESI 

IF ASC(a$)=8 AND i>l THEN 'Backspace ?SI 
i = i-iSI 

position=position-lSI 
IF position=0 THENSI 

positional"! 
END IFSl 

old$=LEFT$ (old$, i-1) +RIGHT$ (old$, LEN (old$) -i) SI 
END IF SI 
END IFSI 
END IFSI 
END IFSI 
END IFSI 
LOCATE z, sSI 

PRINT MID$(old$+" ", i-position+1, inplen ) 'String outputs 
CALL getkey (a$, z, s+position-1) 'get next keySI 
WEND f 
END IFSI 
IF iXposition THENSI 

CALL putstring (old$, z, s, inplen ) SI 
END IF SI 
END SUBSI 
SI 

SUB getint (i ! ,a$, z, s, inplen ,unt!,ob!) STATIC SI 
TASK :Read integer valueSI 
PARAMETER: =>i! old valueSI 

a$ pressed keySI 
z lineSI 
s column SI 

inplen Length of input lineSI 
unt! lower limit SI 
ob! upper limit SI 
< = i ! specified valueSI 
CALL conrealstr (i ! , j$) SI 
loop:SI 
i$ = j$ SI 

CALL getstring (i$, a$, "1234567890-", z, s, inplen ) SI 
j$=i$SI 

CALL con str real (i$, i ! ) SI 

IF i$-"" OR i ! <unt ! OR i!>ob! THEN 'keep searching while input is valid? 
a$ = " "SI 
GOTO loopSI 
END IFSI 
END SUBSI 

SUB getreal (i !, a$, z, s, inplen ,unt!,ob!) STATICSI 
TASK :Read in real valueSI 
PARAMETER :=>i! old valueSI 

a$ pressed keySI 
z lineSI 
s columnSI 

inplen length of input lineSI 
unt! lower limitSI 
ob! upper limitSI 
<=i ! specified valueSI 
CALL conrealstr (i !, j$) SI 
loopl: SI 
i$=j$SI 
CALL getstring(i$,a$, "1234567890- .", z, s, inplen ) SI 



310 



Abacus Appendix C — The Editor Program 



j$=i$SI 

CALL constrreal (i$,i!) SI 
IF i$="" OR i!<unt! OR i!>ob! THENSI 
a$=" "SI 
GOTO looplSI 
END IFSI 
END SUBf 
I 

SUB get 3real <il !, 12 !,i3!,a$,z,s, inplen , unt !, ob! , modus) STATICSI 
TASK :read 3 Real values in SI 
PARAMETER: =>il! ,121,13! old valuel 
a$ key pressedSI 
z linef 
s columnSl 

inplen Lenght of input line SI 
unt! lower limitSI 
ob! upper limit SI 
modus if=0 no mouse en try SI 

if=-l mouse input {position vector) SI 
if>0 mouse input (Difference vector) SI 
<=il ! , i 2 ! , i3 ! specified valueSI 
SHARED mox ! , moy ! , moz ! , k ! ( ) SI 
CALL con3realstr (il!,i2! , i3! , j$)SI 
IF a $="" THENSI 

CALL getkey (a$, z, s) SI 
END IF SI 

IF ASC(a$)=13 AND modus ><0 THENSI 
IF modus=-l THENSI 
i 1 ! =mox ! SI 
i2!=moy!SI 
i3!=moz!SI 
ELS ESI 

il!=mox!-k! (modus, 1, 0) SI 
i 2 ! =moy ! ~k ! (modu s, 1,1)1 
i3!=moz!~k! (modus, 1 , 2) SI 
END IFSI 

CALL put 3 real ( i 1 ! , i 2 ! , i 3 ! , z , s , 2 6) SI 
ELSESI 
loop2:SI 

i$ = j$ SI 

CALL getstring(i$,a$,"1234567890-.,",z,s, inplen ) SI 
j$=i$fl 

CALL constr3real (i$, il ! , i2 ! , 13 ! ) SI 

IF i$ = ,,M OR il!<unt! OR i2!<unt! OR i3!<unt! OR il!>ob! OR i2!>ob! OR i3!>ob! 
THENSI 

a$=" "SI 
GOTO loop2SI 
END IFSI 
END IFSI 
END SUB SI 
SI 

SUB getkey (a$, z, s) STATICS! 
'TASK :Read one character inSI 
' PARAMETER :=>z lineSI 
' s column Si 

' <=a$ pressed keySI 

CALL setcursor (z, s) SI 
a$=""SI 

WHILE a$ = ""SI 
a$=INKEY$SI 
WENDSI 
CALL setcursor (z, s) SI 



311 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



END SUB<I 



SUB setcursor(z,s) STATIC! 

'TASK :set cursor at specified position! 

■ PARAMETER :=>z lineal 

' s column! 

SHARED cw%,ch%! 

CALL setdrmd& (WINDOW (8) , 2)! . 

LINE (s*cw%-cw%, z*ch%-ch%-l) - (s*cw%, z*ch%-l) , 3, bf! 

CALL setdrmd& (WINDOW (8) , 1)! 
END SUB ! 
! 

I •****•*••••■*■•*••••<![ 

'** DATA ENTRY **! 

I ******************CT 

'The following proceures are similar to the ones 1 
'documented earlier. ! 
! 

SUB getplane(ptr) STATIC! 
'TASK :Read the data for one Plane! 
' PARAMETER :=>ptr points to the element to be read! 
SHARED k! () ,tabs() ,min! ,maxl! 
tabs (0,0) =2 'set tabs for menu SI 
tabs (1,0) =21 
tabs (2,0) =31 
tabs(3,0)=4! 
tabs(4,0)=5! 
tabs (0,1) =101 
tabs (1,1) =221 
tabs(2,l)=4! 
tabs(3,l)=4! 
tabs(4,l)=4! 
nr=0! 

WHILE nr<=4 'wait until last line is overwritten! 
CALL gctkey (a$, tabs (nr, 0) , tabs (nr, 1) ) 1 
IF ASC(a$)=28 THEN 'cursor up?! 
IF nr>0 THEN! 

nr-nr-11 
END IF 1 
ELSE 1 

IF ASC(a$)=29 THEN 'cursor down?! 

nr=nr+l! 
ELSE! 

IF nr=0 THEN 'can you see it? read it 1 

CALL getstring(b$,a$,"yn", tabs (nr, 0) ,tabs(nr,l) , 1)1 
IF b$="y"THEN 'not input! 

k! (ptr,5,2)=l! 
ELSE ! 

k! (ptr,5,2)=0! 
END IF! 
END IF! 
IF nr=l THEN 'Read M! 

CALL getint (k! (ptr, 0,2) , a$, tabs (nr, 0) , tabs (nr, 1) ,5,1 ! , max ! )! 
END IF 1 
IF nr=2 THEN 'A read! 
CALL 
get3real (k! (ptr, 1,0) ,k! (ptr, 1,1) ,k! (ptr, 1,2) , a$, tabs (nr, 0) ,tabs(nr,l) ,26,min! , max ! , 
-D! 

END IF! 

IF nr=3 THEN 'B read! 



312 



Abacus Appendix C — The Editor Program 



CALL 
get3real(k! (ptr,2,0) ,k! (ptr, 2,1) , k! (ptr, 2, 2) , a$, tabs (nr, 0) , tabs (nr, 1) ,26, min! , max ! 
, ptr) SI 

END IFSI 

IF nr=4 THEN ' C readSl 
CALL 
get3real (k! (ptr, 3, 0) , k! (ptr, 3, 1) , k! (ptr, 3, 2) , a$, tabs (nr, 0) , tabs (nr, 1) , 26, rain! , max ! , 
ptr) SI 

END IFSI 
nr=nr+11 
END IFSI 
END IFSI 
WEND1 
END SUB 1 
1 
SUB getcrseg(ptr) STATIC1 

SHARED k ! ( ) , tabs ( ) , min ! , max ! , grad ! , rad ! 1 

tabs(0,0)=21 

tabs(l,0)=2SI 

tabs(2,0)=31 

tabs(3,0)=41 

tabs (4,0) =51 

tabs (5,0) =61 

tabs (6,0) -61 

tabs (0,1) =101 

tabs (1,1) =221 

tabs(2,l)=41 

tabs (3,1) =41 

tabs (4,1) =41 

tabs (5,1) =41 

tabs (6,1) =161 

nr=0SI 

WHILE nr<=6SI 

CALL getkey (a$, tabs (nr , 0) , tabs (nr, 1) )1 
IF ASC(a$)=28 THEN1 
IF nr>0 THEN1 

nr-nr-lSl 
END IF 1 
ELSE1 

IF ASC(a$)=29 THENl 

nr=nr+11 
ELSE SI 

IF nr=0 THENl 

CALL getstring (b$, a$, "yn", tabs (nr, 0) , tabs (nr, 1) , 1) 1 
IF b$ = ,, y"THENl 

k! (ptr,5,2)=11 
ELSE 1 

k! (ptr,5,2)=01 
END IF1 
END IF1 
IF nr=l THENl 

CALL getint (k ! (ptr, 0, 2) ,a$, tabs (nr, 0) , tabs (nr, 1) , b, 1 ! , max! ) 1 
END IF 1 
IF nr=2 THENl 
CALL 
get 3 real (k! (ptr, 1 , 0) , k! (ptr, 1, 1) , k ! (ptr, 1 , 2) , a$, tabs (nr, Q) , tabs (nr, 1 ) , 2 6, min ! , max ! , 
-1)1 

END IF1 
IF nr=3 THENl 
CALL 
get3real (k! (ptr, 2, 0) ,k! (ptr, 2,1) ,k! (ptr, 2, 2) , a$, tabs (nr, 0) , tabs (nr, 1) , 2 6, min! , max ! 
, ptr) SI 



313 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



END IF5 
IF nr=4 THEN5 
CALL 
get3real (k! (ptr,3,Q) , k! (ptr,3,l) , k! (ptr,3,2) , a$, tabs (nr,0) , tabs(nr,l) , 26,min! , max ! 
ptr)5 

END IF5 

IF nr=5 THEN5 

k!=k! (ptr,5,0)*grad!5 

CALL get real (k! , a$, tabs (nr, 0) , tabs (nr, 1) , 8,min! ,max ! ) 5 
k! (ptr,5,0)=radi*k!5 
END IF 5 
IF nr-6 THEN5 

k!=k! (ptr,5,l)*grad!5 

CALL getreai (k! , a$, tabs (nr, 0) , tabs (nr, 1) , 8, mm! , max ! ) 1 
k! (ptr,5, 1 )=rad!*k!5 
END IF 5 
nr=nr+15 
END IF*H 
END IF5 
WEND 5 
END SUBf 
5 
5 
SUB getcrarc(ptr) STATICf 

SHARED k! () , tabs ,min!,max! ,grad! , rad ! SI 

tabs (0,0) =25 

tabs (1,0) =25 

tabs(2,0)=35 

tabs(3,0)=45 

tabs(4,0)=55 

tabs(5,0)=65 

tabs (6,0) =65 

tabs (7,0) =75 

tabs(8,0)=75 

tabs (0,1) =105 

tabs (1,1) =225 

tabs (2,1) ~45 

tabs (3,1) =4 SI 

tabs (4,1) =4 SI 

tabs (5,1 )=4SI 

tabs (6,1) =165 

tabs (7,1) =45 

tabs (8,1) =165 

nr=05 

WHILE nr<=85 

CALL, getkey (a$ , tabs (nr f 0) , tabs (nr, 1 ) ) 5 
IF ASC(a$)=28 THENSI 
IF nr>0 THEN5 

nr=nr-15 
END IF 5 
ELSE 5 

IF ASC(a$)=29 THEN5 

nr=nr+15 
ELSE 5 

IF nr-0 THEN 5 

CALL getstring(b$,a$, "yn", tabs (nr, 0) , tabs (nr, 1) , 1) 5 
IF b$="y"THEN5 

k! (ptr,5,2)=15 
ELSE 5 

k! (ptr, 5, 2) =05 
END 1F5 
END IF5 



314 



Abacus Appendix C — The Editor Program 



IF nr=l THENSI 

CALL getint (k! (ptr, 0,2) , a$, tabs (nr, 0) , tabs(nr,l) ,5,1! , max! ) SI 
END IF f 
IF nr=2 THENSI 
CALL 
get3real (k! (ptr, 1,0) , k! (ptr, 1, 1) , k ! (ptr, 1, 2) , a$, tabs (nr, 0) , tabs(nr, 1) , 2 6,min! , max ! , 
-1)SI 

END IFSI 
IF nr=3 THENSI 
CALL 
get3real(k! (ptr, 2,0) , k! (ptr,2,l) ,k! (ptr,2,2) ,a$,tabs (nr,0) , Labs (nr, 1) , 2 6,min! , max! 
, ptr) SI 

END IFSI 
IF nr=4 THENSI 
CALL 
get3real (k! (ptr,3,0) , k! (ptr, 3, 1) , k! (ptr, 3, 2) , a$, tabs (nr, 0) ,tabs (nr, 1) , 26,min0! , max ! 
, ptr) SI 

END IFSI 

IF nr=5 THENSI 

k!=grad!*k! (ptr, 5,0) SI 

CALL get real (k! , a$, tabs (nr, 0) , tabs(nr, 1) , 8,min! , max ! ) SI 
k! (ptr,5,0)=rad!*k!SI 
END IF SI 
IF nr=6 THENSI 

k!=grad!*k! (ptr,5,l)SI 

CALL getreal (k! , a$, tabs (nr, 0) , tabs (nr, 1) , 8, min! , max ! ) SI 
k! (ptr,5,l)=rad!*k!SI 
END IF SI 
IF nr=7 THENSI 

CALL getreal (k! (ptr, 4,0) , a$, tabs (nr, 0) , tabs (nr, 1),8,0!,1!)SI 
END IF SI 
IF nr=8 THENSI 

CALL getreal (k! (ptr, 4,1) , a$, tabs (nr, 0) , tabs(nr,l) , 8 , ! , 1 ! ) SI 
END IF SI 
nr=nr+lSI 
END IFSI 
END IFSI 
WEND SI 
END SUB SI 
SI 
SI 
SUB get sphere (ptr) STATICSI 

SHARED k! () , tabs (), min!, max! SI 

tabs(0,0)=2SI 

tabs(l,0)=2SI 

tabs(2,0)=3SI 

tabs(3,0)=4SI 

tabs(0,l)=10SI 

tabs(l,l)=22SI 

tabs (2,1) =4SI 

tabs(3,l)=4SI 

nr=0SI 

WHILE nr<=3SI 

CALL getkey (a$, tabs (nr, 0) ,tabs(nr,l) ) SI 
IF ASC(a$)=28 THENSI 
IF nr>0 THENSI 

nr=nr-lSI 
END IF SI 
ELSE SI 

IF ASC(a$)=29 THENSI 

nr=nr+lSI 
ELSE! 



315 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



IF nr=0 THENSI 

CALL getstring(b$,a$, "yn", tabs (nr, 0) , tabs(nr, 1) , 1) SI 
IF b$="y"THENf 

k! (ptr, 5, 2) =15 
ELSE 1 

k! (ptr,5,2)=05 
END IFSI 
END IFSI 
IF nr=l THENSI 

CALL getint (k! (ptr, 0,2) , a$, tabs (nr, 0) , tabs(nr,l) ,5,1!, max! ) SI 
END IF 5 
IF nr=2 THENSI 
CALL 
get3real (k! (ptr,l,0) ,k! (ptr,l,l),k! (ptr,l,2) ,a$, tabs (nr, 0) ,tabs(nr,l) ,26, 
1000!, 1000!, -1)5 
END IF5 
IF nr-3 THEN5 

CALL get real (k! (ptr,2,0) , a$, tabs (nr, 0) ,tabs(nr,l) , 8, 0! , max ! ) SI 
END IF SI 
nr=nr+lSI 
END IFSI 
END IFSI 
WEND SI 
END SUB SI 



SUB getcyl (ptr) STATICSI 

SHARED k! () ,tabs() ,min! , max ! SI 

tabs (0,0) =25 

tabs(l,0)=2SI 

tabs(2,0)=35 

tabs(3,0)=45 

tabs(4,0)=55 

tabs(5,0)=6SI 

tabs (0,1) =105 

tabs (1,1) =225 

tabs (2, i)=45 

tabs(3,l)=45 

tabs(4,l)=4SI 

tabs(5,l)=4SI 

nr=05 

WHILE nr<=5SI 

CALL getkey (a$, tabs (nr, 0) , tabs (nr, 1) ) SI 
IF ASC(a$)=28 THENSI 
IF nr>0 THENSI 

nr=nr-lSI 
END IF SI 
ELSE SI 

IF ASC(a$)=29 THENSI 

nr=nr+lSl 
ELSESI 

IF nr=0 THENSI 

CALL getstring(b$,a$, "yn", tabs (nr, 0) , tabs (nr, 1) , 1) SI 
IF b$="y"THEN5 

k! (ptr,5,2)=lSl 
ELSE SI 

k! (ptr,5,2)=0SI 
END IFSI 
END IFSI 
IF nr=l THENSI 

CALL getint' (k! (ptr, 0,2) , a$, tabs (nr, 0) ,tabs(nr,l) ,5,1!, max! ) SI 
END IF SI 



316 



Abacus Appendix C — The Editor Program 



IF nr=2 THENl 
CALL 
get3real (k! (ptr, 1, 0) ,k! (ptr,l,l) ,k! (ptr, 1,2) ,a$, tabs (nr, 0) , tabs (nr, 1) , 26,min! ,max! 
,-1)1 

END IF1 
IF nr=3 THENl 
CALL 
get3real (k! (ptr, 2,0) , k! (ptr, 2, 1) ,k! (ptr, 2, 2) ,a$, tabs (nr, 0) ,tabs (nr, 1 ) , 26,min! , max ! , 
ptr)1 

END IF1 
IF nr=4 THENl 
CALL 
get3real(k! (ptr, 3,0) , k! (ptr, 3,1) ,k! (ptr, 3, 2) , a$, tabs (nr, 0) , tabs (nr, 1) , 26,min! ,max!, 
ptr) 5 

END IF1 
IF nr=5 THENl 
CALL 
get3real(k! (ptr,4,0),k! (ptr, 4,1) ,k! (ptr, 4, 2) ,a$, tabs (nr, 0) ,tabs(nr,l) , 26,min! , max ! , 
ptr)1 

END IF1 
nr=nr+11 
END IF1 
END IF1 
WEND1 
END SUB 1 

1 
SUB getcylseg(ptr) STATICl 

SHARED k! () ,tabs () ,min! ,max! ,grad! , radial 

tabs (0,0) =21 

tabs (1,0) =21 

tabs (2,0) =31 

tabs (3,0) =41 

tabs(4,0)=51 

tabs(5,0)=61 

tabs(6,0)=71 

tabs(7,0)=7fl 

tabs(0,l)=101 

tabs (1,1) =221 

tabs(2,l)=41 

tabs(3,l)=41 

tabs(4,l)=41 

tabs(5,l)=41 

tabs(6,l)=41 

tabs (7,1) =161 

nr=01 

WHILE nr<=71 

CALL getkey (a$, tabs (nr, 0) , tabs (nr, 1) ) 1 
IF ASC(a$)=28 THEN1 
IF nr>0 THEN1 

nr=nr-11 
END IF 1 
ELSE 1 

IF ASC(a$)=29 THEN1 

nr=nr+H 
ELSE1 

IF nr=0 THEN1 

CALL getstring(b$,a$,"yn", tabs (nr, 0) , tabs (nr,l) , 1)1 
IF b$="y"THEN1 

k! (ptr,5,2)=11 
ELSE 1 

k! (ptr,5,2)=01 
END IF1 



317 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



END IFSI 

IF nr=l THENSI 

CALL getint (k! (ptr, 0,2) , a$, tabs (nr, 0) , tabs (nr, 1) ,5, 1 !,max! ) SI 
END IF SI 
IF nr=2 THENSI 

CALL 
get3real (k! (ptr, 1, 0) , k ! (ptr, 1,1) , k! (ptr, 1,2) , a$, tabs (nr, 0) , tabs(nr,l) , 26, min ! , max! 

,-dsi 

END IFSI 
IF nr=3 THENSI 
CALL 
get:3real(k! (ptr, 2,0) , k! (ptr,2,l) , k '. (ptr, 2, 2) , a$, tabs (nr, 0) , tabs(nr,i) ,26, mini ,max!, 
ptr) SI 

END IFSI 
IF nr=4 THENSI 
CALL 
get3real (k! (ptr, 3,0) ,k! <ptr,3,l) ,k! (ptr, 3, 2) , a$, tabs (nr, 0) , tabs(nr,l) ,26, min! , max ! , 
ptr) SI 

END IFSI 
IF nr=5 THENSI 
CALL 
get3real (k! (ptr,4,0) ,k! (ptr,4, 1) ,k! (ptr, A, 2) , a$, tabs (nr, 0) ,tabs(nr,l) , 26, min! , max ! , 
ptr) SI 

END IFSI 

IF nr=6 THENSI 

k!=grad!*k! (ptr, 5, 0)SI 

CALL getreai (k! , a$, tabs (nr, 0) , tabs (nr, 1) ,2 6, min! , max ! ) \ 
k! (ptr,5,0)-rad!*k!SI 
END IFSI 
IF nr----7 THEN SI 

k!=grad!*k! (ptr, 5,1) SI 

CALL getreai (k! ,a$, tabs (nr, 0) , tabs (nr, 1) , 2 6, min! , max ! ) Si 
k! (ptr,5,l)=rad!*k!SI 
END IFSI 
nr=nr+lS! 
END IFSI 

iTNTn rrr-cn 

WEND SI 
END SUB SI 

SI 
SI 

• ** OUTPUT **SI 

SI 
SUB showelem(ptr) STATICSI 
'TASK :data output of element ptrSI 
' PARAMETER :=>ptr pointer to the specified elements! 
SHARED k! () ,typ$() , empty $, grad !, rad! SI 
LOCATE 1,1SI 
FOR i=l TO 7SI 

PRINT empty$SI 
NEXT iSI 
LOCATE 1, ISI 
PRINT "Body : "SI 
CALL put real (ptr*i ! , 1 , 8, 5) SI 
typ=INT(k! (ptr, 0,0) ) SI 
IF ptr><0 THENSI 
LOCATE 1,1 A SI 
PRINT typ$ (typ)SI 
LOCATE 2, ISI 
PRINT "visible :";SI 



318 



Abacus Appendix C — The Editor Program 



IF k! (ptr,5,2) =0 THEN1 

PRINT "n"1 
ELSE 1 

PRINT "y"1 
END IFl 
LOCATE 2,131 
PRINT "Material: "SI 
CALL putreal(k! (ptr, 0, 2 ) , 2, 22, 5) SI 
IF typ=10 THEN1 
LOCATE 3,11 
PRINT "M :"1 
PRINT "r :"1 

CALL put3real (k! (ptr, 1, 0) ,k! (ptr,l,l),k! (ptr, 1 , 2) , 3 , 4 , 2 6) 1 
CALL putreaKk! (ptr , 2, 0) , 4, 4, 8) 1 
ELSE1 

LOCATE 3,11 
PRINT "M :"1 
PRINT "A :"1 
PRINT "B :"1 

CALL put3real (k! (ptr, 1,0) ,k! (ptr, 1,1) , k! (ptr, 1,2), 3, 4, 2 6) SI 
CALL put3real(k! (ptr, 2,0) ,k! (ptr, 2,1) ,k! (ptr, 2, 2) ,4, 4, 2 6) SI 
CALL put3real (k! (ptr, 3, 0) , k ! (ptr, 3, 1 ) , k! (ptr, 3, 2) ,5, 4, 2 6) SI 
IF typ>=4 THENSI 
IF typ>=20 THENSI 
LOCATE 6,1 SI 
PRINT "C :"SI 

CALL put3real (k! (ptr, 4,0) ,k! (ptr, 4,1) , k! (ptr, 4, 2) , 6, 4, 26) SI 
IF typ=21 THENSI 
LOCATE 7, 11 
PRINT "sw:"SI 
LOCATE 7,131 
PRINT "ew:"1 

CALL put real (grad!*k! (ptr, 5,0) ,7,4,8)1 
CALL put real (grad!*k! (ptr, 5,1) ,7,16,8)1 
END IF1 
ELSE1 

LOCATE 6,11 
PRINT "sw:"1 
LOCATE 6,131 
PRINT "ew:"1 

CALL putreal (grad!*k! (ptr, 5,0) ,6,4,8)1 
CALL putreal (grad!*k! (ptr, 5, 1) , 6, 1 6, 8) 1 
IF typ=5 THEN1 
LOCATE 7, 11 
PRINT "ri:"1 
LOCATE 7, 131 
PRINT "ra:"1 

CALL put real ( k ! (pt r , 4 , ) , 7 , 4 , 8 ) 1 
CALL, putreal. (k ! (ptr, 4 , 1 ) , 7, 1 6, 8) 1 
END IF1 
END IF1 
END IF1 
END IF1 
END IF1 
END SUB1 
1 

SUB putstring(s$, z, s, inplen ) STATICl 
TASK : output of a string of a certain lengthl 
PARAMETER :=>s$ the stringl 
z linel 
s columnl 
inplen Length of output windowl 



3 19 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



LOCATE z,s 'clear specified ranged 

PRINT SPACE$(inplen )! 

LOCATE z,s 'display the string! 

PRINT MID$(s$,l,inplen )! 
END SUB! 



SUB putreal (i! ,z,s,inplen ) STATIC! 
TASK -.Display real value of predetermined length! 
PARAMETER: =>i! the real value! 
z line! 
s column! 

inplen Length of output window! 
CALL conrealstr (i! , s$) ! 
CALL putstring(s$, z, s, inplen )! 
END SUB! 

! 
SUB put3real (il ! , i2 ! , i3 ! , z, s, inplen ) STATIC! 
TASK : display 3 Real values of certain length! 
PARAMETER:=>il!,i2!,i3! the real values! 
z line! 
s column! 

inplen Length of the output window! 
CALL con3realstr (il ! , i2 ! , i3 ! , i$) ! 
CALL putstring (i$, z, s, inplen )! 
END SUB! 
! 

I •••••••••••••••••••Q[ 

'** CONVERSIONS **! 

I *******************C[ 

! 

SUB conrealstr (i ! ,i$) STATIC! 

'TASK : convert real value into string! 

' rounded to 3 decimal places! 

■ PARAMETER: =>i! the real value! 
' <=i $ the string! 

iy=S irw \±: l 1 

j ! -FIX (1 000 ! *i ! + . 5*SGN (i ! ) ) /1000 ! ' round! 

i$-STR$(j!)! 

IF ABS(j!)>0 AND ABS(j!)<l THEN 'if 0<j!<l inserted! 
i$=MID$(i$,l,l)+"0"+MID$(i$,2,LEN(i$) )! 

END IF! 

IF j!>=0 THEN 'if 0<= j ! truncate first place! 
i$=RIGHT$(i$ r LEN(i$)-l)f 

END IF! 
END SUB! 
! 

SUB constrreal(i$,i! ) STATIC! 
'TASK : convert string into real value! 
' PARAMETER :=>i$ the string! 

■ <=i! the real value! 

' i$ if conversion error i$^""! 

i!=VAL(i$)! 
IF i!>=0 THEN! 

IF i!>0 AND i!<l THEN! 

i$=" "+RIGHT$(i$,LEN(i$)-l) 'insert space and cutoff 0% 
ELSE ! 

i$=" "+i$ 'insert space! 
END IF! 
END IF! 

j!=i!-FIX(i!*1000!)/1000! 'round ! 
IF i$XSTR$(i!) OR j!><0 THEN 'Error ?! 



320 



Abacus Appendix C — The Editor Program 



i$=""Sl 

END IF 1 
END SUBSI 
SI 

SUB constr3real (i$,il! ,121,13!) STATICS! 
'TASK : convert one string into 3 real values^ 
' PARAMETER :=>i$ the stringSI 

<=il!,i2!,i3! the real valuesSI 
' i$ if conversion error i$ = ""SI 

Problem=OSI 
i$=i$+","SI 
FOR i=l TO 3SI 

comma=INSTR(i$, ", ") 'Mark comma position^ 
IF comma<=l THEN 'Problem ?SI 

Problem=lSI 
ELSESI 

a$=MID$ (i$, 1, comma-1) 'truncate string to be converted*!! 
i$=RIGHT$ (i$,LEN(i$) -comma) 'mark the rest SI 
CALL const rreal (a$, i ! (i) ) 'converts! 
IF a$="" THEN 'Problem ?SI 

Problem=lSI 
END IF SI 
END IFSI 
NEXT if 
IF Problem=l THENSI 

1$="" Sf 
ELSESI 

i$=" n 

il!=i! (1)% 

i2!=i! (2)fl 

13!=i! (3)5 

END IFSI 

END SUB 1 



SUB con3realstr(il!,i2!,i3!,i$) STATICS! 

'TASK -.convert 3 real values into vector stringSI 

' PARAMETER :=>il! , i2! , i3! the 3 Real valuesSI 

' <=i$ the string^! 

CALL conrealstr (il! ,il$)SI 

CALL conrealstr (i2! ,i2$) SI 

CALL conrealstr (13 ! ,i3$) SI 

i$=il$+", "+i2$+", "+i3$i 
END SUBS! 



i *•************<& 
'** GRAPHICS **SI 

'Routines to display graphics in the projection windows'! 
'the following routines are virtually identical^! 
'to one another, hence the lack of comments'! 
SI 

SUB drawplane (ptr) STATICS! 
SHARED k!()f 



mx 
my 
mz 
ax 
ay 
az 
bx 



=k! (ptr, 1,0) SI 
=k! (ptr, 1,1) SI 
=k! (ptr, 1,2) SI 
=k! (ptr,2,Q)SI 
=k! (ptr,2,l)SI 
=k! (ptr,2,2)SI 
=k! (ptr, 3,0) SI 



321 



Appendix C — The Editor Program 



Amiga 3D Graphic Programming 



by!-k! (ptr, 3,1) SI 
bz!=k! (ptr, 3,2)S! 
WINDOW OUTPUT 1SI 
CALL setpoint (ax! +mx ! , ay! +my ! ) SI 
CALL drawl ine (mx ! , rny ! ) SI 
CALL dr awl i ne (mx ■ +bx ! , my ! +by ! ) 
WINDOW OUTPUT 2 SI 
CALL setpoint (ax ! +mx !,az! +mz ! ) SI 
CALL drawl ine (mx ! , mz ! ) 1 
CALL dr awl i ne (mx ! +bx ! , mz ! +bz ! ) 
WINDOW OUTPUT 3Tl 
CALL setpoint (ay ! +my ! , az ! +mz ! ) SI 
CALL drawl i ne (my ! , mz ! ) 1 
CALL drawl ine (my ! +by ! , mz ! +bz ! ) 
WINDOW OUTPUT 41 
END SUBSI 

1 
SUB drawtriangle (ptr) STATICSI 
SHARED k! () SI 

c! (ptr f 1,0) SI 

-J (ptr, 1,1) SI 

:! (ptr, 1,2)1 

c! (ptr, 2,0) 1 

;! (ptr, 2,1)1 

t! (ptr, 2, 2) SI 

c! (ptr, 3, 0) 1 

c! (ptr, 3,1) 1 

c! (ptr, 3, 2) SI 
WINDOW OUTPUT 11 
CALL setpoint (mx ! , my ! ) 1 
CALL drawl i ne (ax ! +mx ! , ay ! +my ! ) 1 
CALL drawl ine (bx ! +mx ! , by ! +my ! ) 1 
CAT ,L d rawl i ne (mx ! , my ! ) 
WINDOW OUTPUT 2 SI 
CALL Sf point (mx ! , mz ! ) SI 
CALL drawl ine (ax ! +mx ! , az ! +rnz ! ) SI 
CALL draw line (bx ! +mx ! , bz ! +mz ! ) 1 
CALL drawl i ne (mx ! , mz ! ) 
WINDOW OUTPUT 31 
CALL setpoint (my ! , mz ! ) 1 
CALL drawl ine (ay! +my ! , az ! +mz ! ) 1 
CALL drawl ine (by ! +my ! , bz ! +mz ! ) 1 
CALL drawl i ne (my ! , mz ! ) 
WINDOW OUTPUT 41 
END SUB1 

1 



mx 


=k! 


my 


=k' 


mz 


=k! 


ax 


=k! 


ay 


=k! 


az 


=k! 


bx 


=k! 


by 


=k! 


bz 


=k! 



UB drawparall (ptr) STATICS! 
SHARED k! 1 
mx!=k! (ptr, 1,0) SI 
my!=k! (ptr, 1,1) SI 
mz!=k! (ptr, 1,2) SI 
ax!=k! (ptr, 2, 0) SI 
ay!=k! (ptr, 2,1) SI 
az!-k! (ptr, 2, 2) 5 
bx!-k! (ptr, 3,0) SI 
by!=k! (ptr, 3,1) SI 
bz!=k! (ptr, 3, 2) SI 
WINDOW OUTPUT ISf 
CALL setpoi nt (mx ! , my ! ) SI 
CALL drawl ine (ax ! +mx ! , ay ! +my ! ) SI 
CALL drawl ine (ax ! tbx ! +mx ! , ay ! +by ! f my ! 



322 



Abacus 



Appendix C — The Editor Program 



CALL drawl ine (bx!+mx!, by !+my!)1 
CALL drawl i ne (mx! , my ! ) 
WINDOW OUTPUT 2 SI 
CALL setpoint (mx! , mz ! ) 1 
CALL drawl ine (ax! +rnx ! , az ! +mz !) 1 
CALL drawl ine (ax ! +bx ! +mx '. , az ! +bz ! +mz ! ) 1 
CALL drawl ine (bx ! +mx !, bz ! +mz !) SI 
CALL drawline (mx! , mz ! ) 
WINDOW OUTPUT 31 
CALL setpoint (my ! , mz ! ) SI 
CALL drawl ine (ay ! +my ! , az ! +mz ! ) SI 
CALL drawl ine (ay !+by!+my! , az!+bz ! +mz ! ) SI 
CALL drawl ine (by ! +my ! , bz ! +mz ! ) SI 
CALL drawl ine (my ! , mz ! ) 
WINDOW OUTPUT 4 SI 
END SUB SI 



SI 

SUB drawcircle(ptr) STATICSI 

SHARED k! () , pi 2! SI 

mx!=k! (ptr, 1,0)1 

my!=k! (ptr, 1,1) SI 

mz!^-! (ptr / l / 2)SI 

ax!=k! (ptr, 2, 0)1 

ay!=k! (ptr, 2, 1)1 

az!=k! (ptr, 2, 2)1 

bx!=k! (ptr, 3, 0)1 

by!=k! (ptr, 3,1)1 

bz!=k! (ptr,3,2)SI 

WINDOW OUTPUT 1SI 

CALL drawellipse (ax! , ay ! , bx! , by ! , mx! , my ! , ! , pi2 

WINDOW OUTPUT 2 SI 

CALX drawellipse (ax! , az! ,bx! , bz! , mx! , mz ! , ! , pi2 

WINDOW OUTPUT 3 SI 

CALL drawellipse (ay! , az ! , by ! , bz ! , my ! , mz ! , ! , pi2 

WINDOW OUTPUT A SI 
END SUB SI 



!)SI 
!)SI 



SUB drawcrseg(ptr) STATICSI 
SHARED k! ()1 
mx!=k! (ptr, 1, 0) 1 
my!=k! (ptr, 1,1)1 
mz!=k! (ptr, 1,2)1 
ax!=k! (ptr, 2, 0)1 
ay!=k! (ptr, 2, 1)1 
az!=k! (ptr, 2, 2)1 
bx!=k! (ptr, 3, 0)1 
by!=k! (ptr, 3, 1)1 
bz!=k! (ptr, 3,2)1 
sw!=k! (ptr, 5, 0)1 
ew!=k! (ptr, 5, 1)1 
WINDOW OUTPUT 11 

CALL drawellipse (ax! , ay ! , bx ! , by ! , mx ! , my ! , sw ! , ew ! ) 1 
CALL setpoint (ax! *COS(sw! )+bx!*SIN (sw! ) +mx! , ay ! *COS (sw! ) + by! '■ 
CALL drawline (mx! , my ! ) 1 

CALL drawline (ax!*COS (ew! ) +bx! *SIN (ew! ) tmx! , ay ! *COS (ew! ) tby ! ' 
WINDOW OUTPUT 21 

CALL drawellipse (ax! , az ! , bx! , bz ! , mx ! , mz ! , sw! , ew ! ) 1 
CALL setpoint (ax! *COS(sw! )+bx!*SIN (sw! ) +mx! , az ! *COS (sw ! ) +bz! 1 
CALL drawline (mx! , mz ! )1 
CALL drawline (ax!*COS (ew! ) +bx ! *SIN (ew! )+mx! , az! *COS (ew! ) +bz! 



SIN (sw ! 
SIN (ew! 

SIN (sw! 
'SIN (ew! 



) +my ! ) 1 
) + my ! ) 1 

)+mz!)1 
)+mz!) 1 



323 



Appendix C — The Editor Program 



Amiga 3D Graphic Programming 



mx 


=k! 


my 


=k! 


mz 


=k! 


ax 


=k! 


ay 


=k! 


az 


=k! 


bx 


=k! 


by 


=k! 


bz 


=k! 


sw 


=k! 


ew 


=k! 


ri 


=k! 


ra 


=k! 



WINDOW OUTPUT 35 

CALL drawellipse (ay ! , az ! , by ! , bz ! , my ! , mz ! , sw ! , ew ! ) 5 

CALL setpoint (ay ! *COS (sw! ) +by! *SIN (sw! ) +my ! , az ! *COS (sw ! ) +bz ! *SIN (sw ! ) +mz ! ) 5 
CALL drawl ine (my! ,mz! ) 5 

CALL drawline(ay!*COS(ew!)+by!*SIN(ew!)+my! ,az!*COS(ew! ) +bz ! *SIN (ew! ) +mz ! ) 5 
WINDOW OUTPUT 41 
END SUB 5 

5 

SUB drawcrarc(ptr) STATIC5 
SHARED k! ()5 

c! (ptr,l,0)5 
c! (ptr, 1,1)5 
c! (ptr,l,2)5 
:! (ptr,2,0)5 
:! (ptr,2,l)5 
:! (ptr,2,2)5 
-J. (ptr, 3,0)5 
:! (ptr, 3,1)5 
i\ (ptr, 3, 2) 5 
t! (ptr, 5, 0)5 
:! (ptr, 5, 1)5 
c! (ptr, 4, 0) 5 
c! (ptr, 4, 1)5 
WINDOW OUTPUT 15 

CALL drawellipse (ax! *ra! , ay ! *ra! , bx! *ra! , by ! *ra! , mx ! , my ! , sw ! , ew ! ) 5 
CALL drawellipse (ax! *ri ! , ay! *ri ! , bx ! *ri ! , by ! *ri ! , mx ! , my ! , sw ! , ew ! ) 5 
CALL 
setpoint (ax ! *ra! *COS (sw ! ) +bx! *ra ! *SIN (sw ! )+mx! , ay! *ra! *COS (sw! ) +by ! *ra ! *SIN (sw! )+my 
!) 5 

CALL 
drawl ine (ax ! *ri ! *COS (sw ! ) +bx! *ri ! *SIN (sw ! ) +mx ! , ay ! *ri ! *COS (sw ! ) +by ! *ri ! *SIN (sw ! ) +my 
!)5 

CALL 
setpoint (ax ! *ra ! *COS (ew ! ) +bx! *ra ! *SIN (ew ! ) +mx ! , ay! *ra! *COS (ew! )+by !*ra! *SIN (ew! ) +my 
! ) 5 

CALL 
drawl ine (ax!*ri ! "COS (ew ! ) +bx! *ri !*SIN(ew! ) +mx! , ay! *ri! *COS (ew! ) +by !*ri ! *SIN (ew! ) +my 
!)5 

WINDOW OUTPUT 25 

CALL drawellipse (ax! *ra ! , az ! *ra ! , bx ! *ra! , bz ! *ra ! , mx ! , mz ! , sw ! , ew ! ) 5 
CALL drawellipse (ax! *ri ! , az ! *ri ! , bx! *ri ! , bz ! *ri ! , mx ! , mz ! , sw ! , ew ! ) 5 
CALL 
setpoint (ax!*ra! *COS (sw! ) +bx ! *ra!*SIN (sw! ) +mx ! ,az! *ra! *COS ( sw ! ) + bz! *ra!*SIN(sw! ) +m 
z!) 5 

CALL 
drawl ine (ax!*ri !*C0S (sw! ) +bx! *ri! *SIN(sw! ) +mx! ,az! *ri! *COS (sw! ) +bz !*ri ! *SIN (sw! ) +mz 
!)5 

CALL 
setpoint (ax ! *ra ! *C0S (ew ! ) +bx! *ra! *SIN (ew! ) +mx! , az ! *ra!*C0S (ew! ) +bz ! *ra ! *SIN (ew! ) +mz 
!) 5 

CALL 
drawl ine (ax!*ri !*COS(ew! ) +bx! *ri!*SIN(ew! ) +mx! , az! *ri! *COS (ew! ) +bz !*ri !*SIN (ew! )+mz 
!)5 

WINDOW OUTPUT 35 

CALL drawellipse (ay! *ra! , az! *ra! , by ! *ra! , bz ! *rai , my ! , mz ! , sw ! , ew ! ) 5 
CALL drawellipse (ay! *ri ! ,az ! *ri ! , by ! *ri ! , bz ! *ri ! , my ! , mz ! , sw ! , ew ! ) 5 
CALL 
setpoint (ay ! *ra ! *C0S (sw ! ) +by! *ra ! *SIN (sw ! ) +my! ,az! x ra! *COS (sw! ) +bz ! ^ra ! *SIN (sw ! ) +mz 
!) 5 

CALL 
drawl ine ( ay ! *ri ! *COS (sw ! ) +by! *ri !*SIN (sw! ) +my ! , az!*ri!*COS (sw! )+bz!*ri !*SIN (sw! ) +mz 
!)5 



324 



Abacus 



Appendix C — The Editor Program 



CALL 
setpoint (ay!*ra!*COS (ew! ) +by ! *ra! *SIN (ew! ) +my! , az ! *ra! *COS (ew! ) +bz ! *ra ! *SIN (ew ! ) +m 
z!) 1 

CALL 
drawline (ay! *ri!*COS(ew! ) -fby ! *ri ! *SIN (ew! )+my! , az! *ri! *COS (ew ! ) +bz!*ri !*SIN(ew! ) +m 
z!)l 

WINDOW OUTPUT 4! 
END SUB 1 

1 
SUB drawsphere(ptr) STATICS! 

SHARED k! () ,pi2!l 

mx!=k! (ptr, 1, 0) 1 

my!=k! (ptr,!,!)! 

mz!=k! (ptr, 1,2)1 

r!=k! (ptr, 2, 0)1 

WINDOW OUTPUT 1! 

CALL drawellipse(r! , ! , ! , r ! ,mx! ,my ! ,0!,pi2! )! 

WINDOW OUTPUT 21 

CALL drawellipse(r!,0!,0!,r!,mx! ,mz! , ! ,pi2! ) 1 

WINDOW OUTPUT 3! 

CALL drawellipse(r! , ! , 0! , r ! ,my ! ,mz ! , 0!,pi2! )! 

WINDOW OUTPUT 4! 
END SUB 1 

1 



SUB drawcone(ptr) STATIC! 
SHARED k! () ,pi2!l 
mx!=k! (ptr, 1, 0)1 
my!=k! (ptr, 1,1)1 
mz!=k! (ptr, 1,2)1 
ax!=k! (ptr, 2,0)1 
ay!=k! (ptr, 2, 1)1 
az!=k! (ptr, 2, 2)1 
bx!=k! (ptr, 3, 0)1 
by!=k! (ptr, 3,1)1 
bz!=k! (ptr, 3, 2)1 
cx!=k! (ptr, 4, 0) 1 
cy!=k! (ptr, 4,1) 1 
cz!=k! (ptr, 4, 2) 1 
WINDOW OUTPUT 1! 
CALL drawellipse (ax! 
CALL setpoint (ax ! +mx 
CALL drawl ine (ex! +mx 
CALL drawl ine (mx ! -ax 
CALL setpoint (bx! +mx 
CALL drawl ine (ex! +mx 
CALL drawl ine (mx!-bx 
WINDOW OUTPUT 2! 
CALL drawellipse (ax! , az! ,bx! ,bz 
CALL setpoint (ax! +mx 
CALL drawl ine (ex ! +mx 
CALL drawl ine (mx! -ax 
CALL setpoint (bx! +mx 
CALL drawl ine (ex! -i- mx 
CALL drawl ine (mx! -bx 
WINDOW OUTPUT 3! 
CALL drawellipse (ay !, az! , by ! ,bz! 
CALL setpoint (ay ! +my 
CALL drawl ine (cy! +my 
CALL drawline (my ! -ay 
CALL setpoint (by ! +my 
CALL drawline (cy! +my 



ay ! , bx ! , by ! , mx ! , my ! , ! , pi 2 ! ) ( 

, ay ! +my ! ) 1 

, cy ! +my ! ) 1 

,my!-ay!) 1 

, by ! +my ! ) 1 

, cy ! +my ! ) 1 

, my ! -by ! ) 1 



mx! ,mz! ,0!,pi2! ) c 



, az ! +mz ! ) 1 
, cz ! +mz ! ) 1 
,mz!-az!) 1 
, bz ! +mz ! ) 1 
, cz ! +mz ! ) 1 
, mz ! -bz ! ) 1 



, az ! +mz ! ) 1 
, cz ! +mz ! ) 1 
,mz!-az!) <I 
, bz ! +mz ! ) 1 
, cz ! +mz ! ) 1 



my!,mz! , 0!,pi2!) c 



325 



Appendix C — The Editor Program 



Amiga 3D Graphic Programming 



CALL drawl ine (my ! -by ! , mz ! -bz ! ) 
WINDOW OUTPUT 45 
END SUB 5 



mx 


=k! 


my 


=k! 


mz 


=k! 


ax 


=k! 


ay 


=k! 


az 


=k! 


bx 


=k! 


by 


=k! 


bz 


=k! 


ex 


=k! 


cy 


=k! 


cz 


=k! 



SUB drawcyl (ptr) STATIC5 
SHARED k! () ,pi2!5 

c! (ptr, 1,0)1 

c! (ptr, 1,1)5 

c! (ptr, 1,2) 5 

c! (ptr, 2, 0)5 

O. (ptr, 2, 1)5 

O. (ptr, 2, 2)5 

-J. (ptr, 3, 0)5 

c! (ptr, 3, 1)5 

c! (ptr, 3, 2)5 

:! (ptr, 4, 0)5 

c! (ptr, 4, 1)5 

:! (ptr, 4,2)5 
WINDOW OUTPUT 15 

CALL drawellipse (ax! , ay ! ,bx! ,by ! ,mx! ,my ! , ! ,pi2 ! ) 5 
CALL drawellipse (ax! , ay ! ,bx! ,by ! ,mx! + cx! , my !+cy ! , 0! ,pi2 ! ) 
CALL setpoint (ax! +mx !, ay ! +my! ) 5 
CALL drawl ine (ax!+cx! +mx! , ay ! +cy !+my ! ) 5 
CALL setpoint (-ax!+mx! , -ay!+my! )5 
CALL drawl ine (ex! -ax! +mx! , cy ! -ay ! +my ! ) 5 
CALL setpoint (bx!+mx! , by! +my! ) 5 
CALL drawl ine (ex ! +bx ! +mx ! , cy ! +by ! +my ! ) 5 
CALL setpoint (-bx ! +mx ! , -by ! f my ! ) 5 
CALL drawl ine (ex ! -bx ! +mx ! , cy ! -by ! +my ! ) 5 
WINDOW OUTPUT 25 

CALL drawellipse (ax! , az ! , bx ! , bz ! , mx ! , mz ! , ! , pi2 ! ) 5 
CALL drawellipse (ax! , az ! ,bx! , bz ! , mx ! +cx ! , mz ! +cz ! , ! ,pi2 ! ) 
CALL setpoint (ax! +mx ! , az ! +mz ! ) 5 
CALL drawl ine (ax! +cx! +mx! , az ! +cz ! fmz ! ) 5 
CALL setpoint (-ax ! +mx ! , -az i +mz ! ) 5 
CALL drawl ine ( ex ! -ax ! +mx ! , cz ! -az ! +mz ! ) 5 
CALL setpoint (bx ! +mx ! , bz ! +mz ! ) 5 
CALL drawl ine ( ex ! +bx ! +mx ! , cz ! +bz ! +mz ! ) 5 
CALL setpoint (-bx!+mx! , -bz!+mz! )5 
CALL drawl ine (cx!-bx!+mx! ,cz! -bz!+mz! ) 5 
WINDOW OUTPUT 35 
CALL drawellipse (ay !, az !, by ! ,bz! 
CALL drawellipse (ay! , az ! , by ! , bz ! 
CALL setpoint (ay ! +my ! , az ! fmz ! ) 5 
CALL drawl ine (ay !+cy ! +my ! ,az ! +cz 
CALL setpoint (-ay! +my ! , -az !+mz! ) 5 
CALL drawl ine ( cy ! -ay ! +my ! , cz ! -az ! +mz ! ) 5 
CALL setpoint (by ! +my ! , bz ! +mz ! ) 5 
CALL drawl ine (cy ! +by ! +my ! , cz ! +bz ! +mz ! ) 5 
CALL setpoint (-by!+my! ,-bz!+mz! )5 
CALL drawl ine (cy !-by!+my! ,cz!-bz!+mz! ) 5 
WINDOW OUTPUT 45 
END SUB 5 

5 

SUB drawcyl seg (ptr) STATIC5 
SHARED k ! 5 
mx!=k! (ptr, 1, 0)5 
my!=k! (ptr, 1,1)5 
mz!=k! (ptr, 1,2)5 
ax!=k! (ptr, 2, 0)5 
ay!=k! (ptr, 2, 1)5 
az!=k! (ptr, 2, 2)5 



my! ,mz! ,0!,pi2! ) 5 

my ! + cy ! , mz ! + cz ! , ! , p i 2 ! ) ( 

+mz ! ) 5 



326 



Abacus 



Appendix C — The Editor Program 



bx 


=k! 


by 


=k! 


bz 


=k! 


ex 


=k! 


cy 


=k! 


cz 


=k! 


sw 


=k! 


ew 


=k! 



c! (ptr, 3, 0)1 

c! (ptr, 3, 1)1 

:! (ptr, 3,2)5 

c! (ptr, 4, 0) 1 

:! (ptr, 4, 1)? 

c! (ptr, 4,2)1 

-J. (ptr, 5, 0)1 

c! (ptr, 5, 1)1 
WINDOW OUTPUT 1ST 

CALL drawellipse (ax! , ay ! ,bx! ,by ! ,mx! + cx! , my ! 
CALL drawellipse (ax! , ay ! ,bx! ,by ! ,mx! ,my ! , sw! 
CALL set point (mx! ,my ! ) 1 
CALL drawl ine (mx ! +cx ! , my ! +cy ! ) 1 
CALL 
drawline(ax!*COS (ew! ) +bx! *SIN (ew! )+mx!+cx! , ay! 
CALL drawl ine (ax ! *COS (ew!) +bx ! *SIN (ew ! ) +mx ! , 
CALL drawl ine (mx! , my ! ) 1 

CALL drawline (ax ! *COS (sw ! ) +bx!*SIN(sw! ) +mx ! , 
CALL 
drawline (ax ! *COS (sw! ) +bx! *SIN (sw! )+mx!+cx! ,ay! 
CALL drawline (mx ! +cx !, my! +cy ! ) 1 
WINDOW OUTPUT 21 

CALL drawellipse (ax! , az ! ,bx! ,bz! ,mx! +cx! , mz ! 
CALL drawellipse (ax! , az ! ,bx! ,bz ! ,mx! ,mz ! , sw! 
CALL setpoint (mx! ,mz! ) 1 
CALL drawl ine (mx ! +cx ! , mz ! +cz ! ) 1 
CALL 
drawline (ax! *COS (ew! ) +bx! *SIN (ew! ) +mx!+cx! , az ! 
CALL drawline (ax! *COS (ew ! ) +bx! *SIN (ew! )+mx!, 
CALL drawline (mx ! ,mz! ) 1 

CALL drawline (ax!*COS(sw! ) +bx!*SIN (sw! ) +mx ! , 
CALL 
drawline (ax!*COS (sw! ) +bx!*SIN(sw! ) +mx!+cx! , az 
CALL drawline (mx ! +cx ! , mz ! +cz ! ) II 
WINDOW OUTPUT 31 

CALL drawellipse (ay! , az ! ,by ! , bz! , my ! +cy ! , mz 
CALL drawellipse (ay! , az ! ,by ! , bz ! ,my ! ,mz ! , sw! 
CALL setpoint (my! ,mz! ) 1 
CALL drawline (my! +cy ! , mz ! +cz ! ) 1 
CALL 
drawline (ay ! *COS (ew! ) +by! *SIN (ew! ) +my!+cy! , az 
CALL drawline (ay ! *COS (ew ! ) +by ! *SIN (ew! )+my! / 
CALL drawline (my! ,mz! ) 1 

CALL drawline (ay ! *COS (sw ! ) +by ! *SIN (sw! )+my!, 
CALL 
drawline (ay! *COS (sw! ) +by ! *SIN (sw! ) +my!+cy!,az 
CALL drawl ine (my ! +cy ! , mz ! +cz ! ) 1 
WINDOW OUTPUT 41 
END SUB 1 



+ cy ! , sw! , ew! ) ( 
, ew ! ) 1 



! *COS (ew ! ) +by ! *SIN (ew ! ) +my ! +cy ! ) 1 
ay ! *COS (ew ! ) +by ! *SIN (ew ! ) +my ! ) 1 

ay!*COS(sw! ) +by ! *SIN (sw! ) +my ! ) 1 

!*COS(sw! )+by! *SIN(sw! ) +my!+cy! )1 



+cz ! , sw! ,ew! ) 1 
, ew ! ) 1 



*COS (ew ! ) +bz ! *SIN (ew ! ) +mz ! +cz ! ) 
az ! *COS (ew ! ) +bz ! *SIN (ew ! ) +mz ! ) 1 

az!*COS(sw!)+bz!*SIN (sw! )+mz! )1 

*COS(sw! ) +bz!*SIN (sw! )+mz!+cz! H 



+ cz ! , sw! , ew! ) ( 
, ew ! ) 1 



*COS (ew ! ) +bz ! *SIN (ew ! ) +mz ! +cz ! ) 
az ! *COS (ew ! ) +bz ! *SIN (ew ! ) +mz ! ) 1 

az ! *COS (sw ! ) +bz ! *SIN (sw ! ) +mz ! ) 1 

*COS(sw! ) +bz!*SIN(sw! ) +mz!+cz! ) c 



SUB drawspheriod(ptr) STATIC1 
SHARED k! () ,pi2!1 



mx 
my 
mz 
ax 
ay 
az 
bx 
by 
bz 
ex 



=k! (ptr, 1,0)1 
=k! (ptr, 1,1)1 
=k! (ptr, 1,2)1 
=k! (ptr, 2, 0)1 
=k! (ptr, 2, 1)1 
=k! (ptr, 2, 2)1 
=k! (ptr, 3, 0)1 
=k! (ptr, 3, 1)1 
=k! (ptr, 3, 2)1 
=k! (ptr, 4,0)1 



327 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



cy!=k! (ptr, 4,1)5 
cz!=k! (ptr,4,2)? 
WINDOW OUTPUT 1? 

CALL drawellipse (ax! , ay ! ,bx! , by ! , mx ! , my ! , ! ,pi2! ) ? 
CALL drawellipse (ax! , ay ! , ex ! , cy ! , mx ! , my ! , ! ,pi2 ! ) ? 
WINDOW OUTPUT 211 

CALL drawellipse (ax! , az ! ,bx ! , bz ! , mx! , mz ! , ! , pi2 ! ) ? 
CALL drawellipse (ax ! , az ! , ex ! , cz ! , mx ! , mz ! , ! , pi 2 ! ) ? 
WINDOW OUTPUT 3? 

CALL drawellipse (ay! , az ! ,by ! , bz ! , my ! , mz ! , ! , pi2 ! ) SI 
CALL drawellipse (ay! , az! , cy! , cz! , my! ,mz! , ! ,pi2 ! ) SI 
WINDOW OUTPUT 4 SI 
END SUB ? 



SUB drawellipse (ax! , ay ! , bx! , by ! , mx ! , my ! , sw ! , ewi ) STATIC? 
TASK :draw ellipse in current output windowSI 
ay!,bx!,by! span of ellipse? 
my! center point of ellipse? 
ew! the start angle and end angle? 
to be used? 
SHARED maxlines,pi2!? 
alpha !=sw ! ? 

numlines=ABS (sw ! -ew !) *max lines/pi 2 ! 'Compute number of lines? 
IF numlines=0 THEN? 

numlines=max lines 'if sw!=ew!, draw full ellipse? 
beta!--=pi2 ! /maxlines? 
ELSE ? 

beta! =ABS (sw! -ew! ) /numlines 'compute increment angle? 
END IF? 

x!=ax!*COS (alpha! ) +bx!*SIN (alpha! )+mx! 'compute start point? 
y ! =ay ! *COS (alpha ! ) +by ! *SIN (alpha ! ) +my ! ? 
CALL setpoint (x ! , y ! ) 'Start point output? 
FOR i=l TO numlines? 

alpha! =alpha ! +beta ! 'compute new angle? 

x!=ax! *COS (alpha! )+bx!*SIN (alpha !) +mx! 'compute new point? 
y !=ay! *COS (alpha! ) +by ! *SIN (alpha! ) +my ! ? 

CALL drawl ine (x! , y ! ) 'draw line from old point to new? 
NEXT i? 
END SUB? 



PARAMETER: => ax 
mx 
sw 



SUB setpoint (x ! ,y! ) STATIC? 

'TASK : set point in current output window? 

' PARAMETER :=>x! / y! Point coordinate? 

SHARED mx ! , my ! , mz ! , factor! , xcorrf ac ! , colour? 
sw i ndo w=WI NDOW ( 1 ) ? 
IF swindow=l THEN? 

LINE ( (x ! -mx! ) *xcorrfac! *f actor ! , (my! -y ! ) * factor ! ) - ( (x! - 
mx! ) *xcorrfac! * fact or ! , (my! -y ! ) * factor ! ) , colour? 
ELSE? 

IF swindow=2 THEN? 

LINE ( (x ! -mx ! ) *xcorrfac! *f actor ! , (mz ! -y ! ) *f actor ! ) - ( (x ! - 
mx! ) *xcorrfac! * fact or ! , (mz ! -y ! ) * factor ! ) , colour? 
ELSE? 

IF swindow-3 THEN? 

LINE ( (my !-x! ) *xcorrfac !* factor ! , (mz ! -y ! ) * factor! ) - ( (my ! - 
x! ) *xcorrfac! *f actor! , (mz ! -y! ) *f actor ! ) , colour? 
END IF? 
END IF? 
END IF? 
END SUB? 



328 



Abacus Appendix C — The Editor Program 



SUB drawl ine (x! ,y! ) STATIC! 

'TASK :draw line from last point to specified point! 

'PARAMETER: =>x! ,y! Point coordinates! 

SHARED mx! , my ! , mz ! , factor! ,xcorrfac! , colour! 
swindow=WINDOW(l) ! 
IF swindow=l THEN! 

LINE -( (x!-mx! ) *xcorrfac! *f actor! , (my !-y! )* factor ! ) , colour! 
ELSE! 

IF swindow=2 THEN! 

LINE -( (x!-mx! ) *xcorrfac! *f actor! , (mz! -y ! ) *f actor! ) , colour! 
ELSE! 

IF swindow=3 THEN! 

LINE -( (my! -x! ) *xcorrfac! * factor ! , (mz!-y ! ) * fact or! ) , colour? 
END IF! 
END IF! 
END IF! 
END SUB! 

! 

i • •••••••••****<j 

'** DISKETTE **! 

! 
SUB loadmat STATIC! 

'TASK :load the Material list from disk! 
' WARNING! no test for existing file ! 

SHARED mat! () , matnum, matpt r, legchar$, File$! 
WINDOW 5,"Load Material", (0, 129) - (314, 150) , 0, 1! 
PRINT "Name:"! 

CALL getstring(File$, " " , legchar$, 1, 6, 10) 'get filename! 
IF File$><"" THEN 'if file$="" then cancel! 
OPEN File$+".mat" FOR INPUT AS 1! 
INPUT #1, quantity! 
WHILE NOT (EOF (1))! 

CALL newmat (matptr) ! 
FOR i=0 TO 6! 

INPUT #1, mat! (matptr, i)! 
NEXT i! 
WEND ! 
CLOSE 1! 
END IF! 

WINDOW CLOSE 5! 
WINDOW OUTPUT 4! 
END SUB! 
! 

SUB savemat STATIC! 

'TASK : save material list currently in memory to disk! 
SHARED mat! (), matnum, legchar$, Fiie$! 
WINDOW 5,"Save Material", (0, 129) - (314, 170) , 0, 1! 
PRINT "Name:"! 
PRINT "from: 1" SI 
PRINT "to :"! 
mfrom!=l! 
mto!=matnum! 

CALL putreal (mto!,3, 6,10) 'Read all data! 
CALL getstring(File$, " ", legchar$, 1, 6, 10) ! 
CALL getint (mfrom!, " ", 2, 6, 10, 1 ! , matnum* 1 ! ) ! 
CALL getint (mto! , " ", 3, 6, 10,mf rom! , matnum*l ! ) ! 
IF File$><"" THEN 'if file$="" then cancel! 
OPEN File$+" .MAT" FOR OUTPUT AS 1! 
WHILE mfrom!<mto! AND mat ! (mto ! , 0) =-1! 
mto!=mto! -1! 



329 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



WEND f 

PRINT #l,mto!-mfrom!+lSI 
FOR ptr=mfrom! TO mto! SI 
FOR i=0 TO 6! 

IF mat! (ptr,0)=-l THENSI 

ELSE SI 

PRINT #l,mat! (ptr, i) SI 
END IFSI 
NEXT if 
NEXT ptrf 
CLOSE 1ST 

KILL File$+".MAT.info"f 
END IFf 

WINDOW CLOSE 5f 
WINDOW OUTPUT 4f 
END SUM 

f 
SUB loadlist STATICf 

'TASK :See corresponding routine for material list f 
SHARED k! () , knum, ptr, legchar$ / File$f 
WINDOW 5, "Load List", (0, 129) - (314, 150) , 0, If 
PRINT "Name: "SI 

CALL getstring(File$, " ",legchar$, 1, 6, 10) SI 
IF File$><"" THENSI 

OPEN File$+".list" FOR INPUT AS 1SI 
INPUT #l,quantitySI 
WHILE NOT (EOF (1)) SI 
CALL newel em ( pt r ) f 
FOR i=0 TO 5 SI 

INPUT #l,k! (ptr,i,0),k! (ptr,i,l),k! (ptr, i, 2) SI 
NEXT iSI 
WEND SI 
CLOSE ISI 
END IFSI 

WINDOW CLOSE 5 SI 
/vxNDOW OUTPUT i ii 
CALL showelem(ptr) SI 
END SUBSI 
SI 

SUB savelist STATICSI 

'TASK :See corresponding routine for material list SI 
SHARED k! (),knum, legchar$,File$SI 
WINDOW 5, "Save List", (0, 129) - (314, 170) , 0, ISI 
PRINT "Name: "SI 
PRINT " from: 1" SI 
PRINT "to :"SI 
mfrom!=if 
mto! =knumf 

CALL putreal (mto! ,3,6,10)1 
CALL getstring(File$, " ", legchar$, 1, 6, 10) 1 
CALL getint (mfrom! , " ", 2, 6, 10, 1 ! , krtum*l ! ) SI 
CALL getint (mto! , " ", 3, 6, 10, mf rom! , knum*l ! ) SI 
IF File$><"" THENSI 

OPEN File$+ ,! .LIST" FOR OUTPUT AS ISI 
quantity=0SI 

FOR i=mfrom! TO mto! 'determine number of elements to be savec 
IF k! (i,0,0) ><-l THENSI 

quant ity=quantity+lf 
END IFSI 
NEXT if 
PRINT #1, quantity SI 



330 



Abacus Appendix C — The Editor Program 



FOR ptr=mfrom! TO mto ! 1 

IF k! (ptr,0,0)x-l THEN 'forget blank elements'! 
FOR i=0 TO 51 

PRINT #l,k! (ptr,i,0) ;", ";k! (ptr, i, 1) ; ", "; k ! (ptr,i,2) ( 
NEXT il 
END IFSI 
NEXT ptrl 
CLOSE 11 

KILL File$+".LIST.info"1 
END IFf 

WINDOW CLOSE 51 

WINDOW OUTPUT 41 

END SUB 1 



'** TRANSFORMATION **1 
i **********************cjj 

1 

SUB rotation (ptr) STATIC1 
'TASK : rotate body by three anglesl 
' PARAMETER :=>ptr points to the bodyl 
SHARED k! () ,grad!,rad!,min!,max!1 
IF ptr><0 THEN1 

WINDOW 5,"Rotation", (0, 129) - (314, 170) ,4,11 
vx!=grad! *vx! 1 
vy !=grad! *vy! 1 
vz!=grad!*vz!l 
LOCATE 2,11 
PRINT"V :"1 

PRINT"q<uit,d<o,c<opy&do : "1 
CALL put3real (vx! , vy ! , vz ! , 2, 4, 2 6) 1 

CALL get3real (vx! ,vy! ,vz! , " " , 2, 4, 26,min ! , max! , 0) 1 
CALL getstring(a$," " , "qcd", 3, 21, 1 ) 1 
vx!=rad! *vx!1 
vy!=rad! *vy ! 1 
vz!=rad!*vz!1 
WINDOW CLOSE 51 
WINDOW OUTPUT 41 
IF a$X"q" THEN1 
IF a$="c" THEN1 

CALL copy (ptr) 1 
END IF1 
IF k! (ptr,0,0)>=20 THEN 1 

til=41 
ELSE1 

til=31 
END IF1 
FOR i=2 TO till 

a!=k! (ptr, i, 0) *COS (vz! ) -k! (ptr, i, 1) *SIN (vz ! ) 1 
b!=k! (ptr, i,0) *SIN(vz!)+k! (ptr,i, 1) *COS (vz ! ) 1 
c!=a!*SIN(vy! )-k! (ptr, i, 2) *COS (vy ! ) 1 
k! (ptr,i,0)=a!*COS(vy!)+k! (ptr, i, 2) *5IN (vy ! ) 1 
k! (ptr, i, l)=c! *SIN(vx! ) +b!*COS (vx! ) 1 
k! (ptr,i,2)=b!*SIN(vx!)-c!*COS(vx! )1 
NEXT il 

CALL showelem(ptr) 1 
IF k! (ptr, 5, 2) =1 THEN1 

CALL drawelem(ptr)1 
END IF 1 
ELSE 1 

WINDOW CLOSE 51 



331 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



END IF1 
END IF1 
END SUBl 
1 

SUB translation (ptr) STATIC1 
'TASK :move one body by one vectorl 
1 PARAMETER :=>ptr points to the bodyl 
SHARED k ! ( ) , min ! , max ! 1 
IF ptr><0 THENl 

WINDOW 5, "Translation", (0, 129) - (314, 170) ,4,11 
LOCATE 2,11 
PRINT"V :"1 

PRINT"q<uit,d<o,c<opy&do : "1 
CALL put3real (vx! , vy ! , vz! , 2, 4, 2 6) 1 
CALL get3real (vx! , vy ! , vz ! , "", 2, 4, 26, min! ,max! ,-l) c 
CALL getstring(a$," ", "qcd", 3, 21, 1) 1 
WINDOW CLOSE 51 
WINDOW OUTPUT 41 
IF a$X"q" THEN1 
IF a$="c" THEN1 

CALL copy (ptr) 1 
END IF1 

k! (ptr,l, 0)=vx!1 
k! (ptr,l,l)=vy!1 
k! (ptr,l,2)=vz!1 
CALL showelem(ptr) 1 
IF k! (ptr, 5, 2) =1 THEN1 

CALL drawelem (ptr) 1 
END IF 1 
ELSE 1 

WINDOW CLOSE 51 
END IF1 
END IF1 
END SUB1 
1 

SUB sizing (ptr) STATIC1 
•TASK :size one body 1 
' PARAMETER :=>ptr points to the bodyl 
SHARED k ! ( ) , min ! , max ! 1 
IF ptr><0 THEN1 

WINDOW 5, "Sizing", (0, 129) - (314, 170) , 4, 11 
LOCATE 2,11 
PRINT"V :"1 

PRINT"q<uit,d<o,c<opy&do : "1 
CALL put3real(vx!,vy! , vz! , 2, 4, 26) 1 
CALL get3real (vx! ,vy! ,vz!," ", 2, 4, 26, min! ,max! , 0) c 
CALL getstring(a$, " ", "qcd", 3, 21, 1) 1 
WINDOW CLOSE 51 
WINDOW OUTPUT 41 
IF a$X"q H THEN1 
IF a$="c" THEN1 

CALL copy (ptr) 1 
END IF1 
IF k! (ptr,0,0)>=20 THEN 1 

til=41 
ELSE1 

til=31 
END IF1 
FOR i=2 TO til 1 

k! (ptr,i,0)=vx!*k! (ptr, i, 0)1 
k! (ptr,i,l)=vy!*k! (ptr, i, 1)1 
k! (ptr,i,2)=vz!*k! (ptr, i, 2)1 



332 



Abacus Appendix C — The Editor Program 



NEXT iSI 

CALL showelem(ptr) SI 

IF k! (ptr, 5,2)=1 THENSI 

CALL drawelem. (ptr) SI 

. END IF SI 

ELSE SI 

WINDOW CLOSE SSI 

END IFSI 

END IF SI 

END SUBSI 

Si 

SI 

• ********************* en 

'** SYSTEM ROUTINES **SI 
i ****** ***************qj 

SI 
SI 

S UB copy (ptr) S T A T I C SI 
'TASK -.copy one body Si 
' PARAMETER :=>ptr points to the bodySI 
SHARED k! ( ) SI 

IF ptr><0 THEN 'not the starting element SI 
old-ptr 'save pointerS! 
CALL n ewe 1 err ( pt r; ) ' c re a t e new s pa ce SI 
FOR i=0 TO 5 ' copy SI 
FOR j-0 TO 2 SI 

k! (ptr, i, j)=k! (old,!, j ) SI 
NEXT jSI 
NEXT LSI 
END IFSI 
END SUBSI 
SI 

SUB copier (ptr) STATICSI 

'TASK : copies a body and displays its dataSI 
1 PARAMETER :=>ptr points to the body SI 
IF ptrxO THENSI 
CALL copy (ptr) SI 
CALL showelem(ptr)Sl 
END IFSI 
END SUB SI 
SI 

SUB deleter (ptr) STATICSI 
'TASK : delete one body? 
' PARAMETER :=>ptr points to the body SI 
SHARED k! () , kfreeSl 

IF ptrXO THEN 'not the starting eiementSI 
FOR i = TO 5 'DeleteSI 
FOR j = TO 2 SI 

k! (ptr,i, ])-0SI 
NEXT jSI 
NEXT i SI 

k ! (ptr, 0, 0) = -I 'Add body to tree listSI 
k ! (pt r , , 1 ) -=k f reeSI 
kf ree=ptrSI 
CALL lefts (ptr:) SI 
END IF SI 
END SUBSI 

or 

SUB lefts (ptr) STATICSI 

'TASK :get element to left of current elernerntSI 

' PARAMETER :=>ptr points to current bodySI 
SHARE!) k! ()SI 



333 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



IF ptrXO THEN SI 

ptr=ptr-lSI 
END IFSl 
WHILE k! (ptr,0,0)=-11 

ptr=ptr-lSI 
WENDSI 

CALL showelem(ptr) SI 
END SUB 1 

SI 
SUB rights (ptr) STATICSI 

'TASK :get element to right of current elements 

■ PARAMETER :=>ptr pointer to current bodySI 
SHARED k ! ( ) , knumSI 
old=ptrSI 
IF ptr<knum THENSI 

ptr=ptr-flSI 
END IFSI 
WHILE k! (ptr,0,0)=-l AND ptr<knumSI 

ptr=ptr+lSI 
WENDSI 
IF k! (ptr,0,0)=-l THENSI 

ptr=old SI 

ELSESI 

CALL showelem(ptr) SI 
END IFf 
END SUBSI 



SUB liob(mx!,my! ,mz! ) STATICS! 

'TASK : read coordinates of upper left hand corned 

' PARAMETER : =>mx !, my ! ,mz ! old coordinates! 

' <=mx ! , my ! , mz ! new coordinates! 

SHARED min! , max ! SI 

CALL ge 1 3 r ea 1 { mx ! , my ! , mz ! , " " , 9 , 1 2,26, mi n ! , max ! , - 1 ) SI 
END SIM 
SI 

SUB setf actor (f! ) STATICSI 
'TASK :read the new sizing factorSI 

' PARAMETER :=>f! old factorSI 
' <=f! new factorSI 

CALL getreal(f!, M ", 11 , 8, 8, . 015625, 64 ! ) SI 
END SUBSI 
SI 

SUB f actor2 ( f ! ) STATICSI 
'TASK :multiply factor! by 2S! 

' PARAMETER: =>f! old factorSI 
' <=f! new factor^ 

IF f!<=32 THENSI 
f !=f !*2SI 
CALL put real (f ! ,11, 8, 8) SI 

END IF SI 
END SUBSI 
SI 

SUB fact or ha If (f! ) STATIC SI 
'TASK : multiply factor! with 0.5SI 

' PARAMETER :=>f! old factorSI 
' <=f! new factor! 

IF 1/f! <=32 THENSI 
f!=f!*.5SI 
CALL putreal (f ! ,11, 8, 8) SI 

END IFSI 



334 



Abacus Appendix C — The Editor Program 



END SUB! 
! 

SUB setlines (maxlines) STATIC! 

'TASK : read max number of lines allowed for drawing a circled 
• PARAMETER :=>maxlines old valued 
' <=maxlines new valued 

i ! =maxl ines! 

CALL getint(i!," ",11, 24, 3, 1 ! , 50 ! ) SI 
maxlines=i ! 1 
END SUB 1 
! 

SUB showandwait (ptr) STATIC! 

'TASK .-display data for a body then moves the upper left ! 
' corner so that it appears in the middle of the screenl 

' or the body appears on the screen in color! 

'PARAMETER: <=ptr points to desired body! 

SHARED knum, k! () , factor! , mx ! , my ! , mz ! , colour, xcorrfac! ! 
IF ptrXO THEN! 

WINDOW 5, "Show", (0, 129) - (314, 170) , 4, 11 
LOCATE 2, If 
PRINT"Body : "! 
PRINT"D<ata,M<iddle,C<olor :"! 
CALL putreal(ptr*l!, 2, 9,10)1 
p!=ptr<K 

CALL getreal(p!," ", 2, 9, 10, 1 ! , knum*l ! ) 1 
CALL getstring(a$, " ,s , "dmc", 3, 23, 1) 1 
WINDOW CLOSE 51 
WINDOW OUTPUT 41 
IF k! (p! ,0,0)><-l THEN'l 
IF plxptr THEN1 
ptr-p!l 

CALL showelem (ptr) 1 
END IF 1 
IF a$X"d" THEN! 
IF a$= ,l m" THEN1 

mx!=k! (ptr, 1, 0) -149/xcorrfac! /factor! 'compute new upper left corner 
my ! =k ! (ptr , 1,1) +57/ factor ! 1 
mz ! =k ! (ptr, 1, 2) +57/f actor ! 1 

CALL put3real (mx! , my ! , mz ! , 9,12, 26) 'and display! 
ELSE! 

col our =31 

CALL d r a we 1 e m ( p t r ) 1 
a$=""5 

WHILE a$-" n ! 
a$-INKEY$! 
WEND! 
colour=ll 

CALL drawelem(ptr) 1 
END IF! 
END IF! 
END IF 1 
END IF ! 

END SUB! 
1 

SUB refresh STATIC! 
'TASK : Refresh screen! 
SHARED k! () , knum! 
FOR i=l TO 3! 

WINDOW OUTPUT il 
CLS! 
NEXT i! 
FOR i=l TO knum! 



335 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



IF k!(i,5,2)=l AND k!(i,0,0)X-l THENf 

CALL drawelem(i)f 
END IFf 
NEXT i f 

WINDOW OUTPUT 4 f 
END SUM 
f 

SUB drawelem(ptr) STATICf 
•TASK :draw current bodyf 
' PARAMETER :=>ptr points to the bodyf 
SHARED k ! ( ) , mx ! , my ! , mz ! f 
IF ptr><0 THEN SI 
CALL busymousef 
typ=k! (ptr,0, 0)f 
IF typ=0 THENf 

CALL drawplane (ptr) SI 
END IFf 
IF typ=l THENf 

CALL drawtriangle(ptr)f 
END IFf 
IF typ=2 THENf 

CALL drawparall (ptr)f 
END IFf 
IF typ=3 THENf 

CALL drawcircle (ptr)f 
END IFf 
IF typ=4 THENf 

CALL drawcrseg (ptr) f 
END IFf 
IF typ=5 THENf 

CALL drawcrarc (ptr) f 
END IFf 
IF typ=10 THENf 

CALL drawsphere (ptr) f 
END IFf 
IF typ-20 THENf 

CALL drawcyl (ptr)f 
END IFf 
IF typ=21 THENf 

CALL drawcyl seg (pt r ) f 
END IFf 
IF typ-22 THENf 

CALL drawcone (ptr) f 
END IFf 
IF typ-24 THENf 

CALL drawspheriod(ptr) f 
END IFf 

CALL lazymousef 
F^ND IFf 
END SUBf 
f 

SUB getelem(ptr) STATICf 
'TASK :Read the necessary body dataf 
' PARAMETER : pt r points to the specified bodyf 
SHARED k ! ( ) f 
typ=k! (ptr, 0, 0) f 
IF typ<-3 AND ptr>0 THEN f 

CALL getplane (ptr)f 
END IF f 
IF typ=4 THENf 

CALL getcrseg(ptr)f 
END IFf 



336 



Abacus Appendix C — The Editor Program 



IF typ=5 THEN! 

CALL getcrarc(ptr)! 
END IF! 
IF typ=10 THEN! 

CALL get sphere (ptr) ! 
END IF! 
IF typ=20 OR typ=22 OR typ=24 THEN ! 

CALL getcyl (ptr)! 
END IF! 
IF typ=21 THEN! 

CALL getcylseg(ptr)! 
END IF! 
IF k! (ptr, 5, 2) =1 THEN! 

CALL drawelem(ptr)! 
END IF ! 
END SUB! 
! 

SUB finish (quit) STATIC! 
'TASK : Confirms quitting program! 
■ PARAMETER: =>qu it -0! 
' <=quit =0 =>no cancel ! 

• =1 => cancel! 

SHARED gadget%()! 

WINDOW 5," QUIT ", (0, 129) - (314, 150) , 0, 15 
PRINT "Really ? "! 

CALL initgadget (110, 3, 15, 30, 1, 5, nrl%, 100, -1) ! 
CALL initgadget (160,3,15, 60, 1, 5, nr2%, 200, -1) ! 
WHILE gadget%(nrl%,4)><0 AND gadget% (nr2%, 4) ><0! 
WEND! 
IF gadget%(nrl%,4)=0 THEN! 

quit=l! 
END IF! 

WINDOW CLOSE 5 ! 
CALL deletegadget (nrl%)! 
CALL deletegadget (nr2%) ! 
END SUB! 
! 

SUB newelem(ptr) STATIC! 

'TASK :get address of free place in list! 
1 PARAMETER: <=ptr points to this area! 
SHARED kfree,k! (),knum! 
IF kfree<knum THEN! 
ptr=kfree! 
kfree=k! (ptr, 0,1)! 
k! (ptr,0,0)=0! 
k! (ptr, 0,1) =05 
k! (ptr, 0,2) =15 
END IF ! 
END SUB! 



SUB actlwith4 STATIC! 

•TASK : activate Menu 1 to 4! 

CALL busymouse ! 

MENU 1,0,1, "Transform. "! 

MENU 1,1,1, "Rotation "! 

MENU l,2,l,"Translation 

MENU 1,3,1, "Enlarge 

MENU 1,4,1, "Copy 

MENU 1,5,1, "Delete "D M( 3 

MENU 1, 6,1, "Correction "K"^ 



337 



Appendix C — The Editor Program 



Amiga 3D Graphic Programming 



MENU 
MENU 
MENU 
MENU 



MENU 2,0,1, 
2,1,1, 
2,2,1, 
2,3,1, 
2,4,1, 
MENU 2,5,1, 
MENU 2,6,1, 
MENU 2,7,1, 
MENU 2,8,1, 
MENU 2, 9, 1, 
MENU 2,10,1 
MENU 2,11,1 



'Body 

•Plane 

'Triangle 

'Parallelogram 

'Circle 

'Circle segment 

'Arc 

'Sphere 

'Cylinder 

'Cylinder seg. 

, "Cone 

, "Spheroid 



MENU 3,0,1, "Disk "SI 

MENU 3, 1,1, "Load Lisf'SI 

MENU 3, 2,1, "Load Mat "SI 

MENU 3, 3,1, "Save Lisf'SI 

MENU 3, 4,1, "Save Mat "SI 



MENU 4,0,1, "Operations "SI 

MENU 4,: 

MENU 4,; 

MENU 4,; 

MENU 4, 

MENU 4,1 



1,1, "Left L" 
2,1, "Right R" 
3,1, "Segment " 
4,1, "Factor 
5,l,"Factor*2 *" 
MENU 4,6,i,"Factor/2 /" 
MENU 4,7,1, "Mat. editor " 
8,1, "Refresh A R" 
Show S" 
"Lines " 
"Quit 



MENU 
MENU 4, 
MENU 4, 
MENU 
CALL lazymouseSI 
END SUBS! 



,9,1," 
,10,1, 

,11,1, 



SUB entactlwith4 STATIC 



' TASK 
CALL 
SI 

MENU 
MENU 
MENU 



: deactivate MENU 1 TO 4SI 
busy mouse SI 



1, 0, 0, "Transform 
1, 1, 1, "Rotation 
1, 2, 1, "Translation 
MENU 1,3, 1, "Enlarge "SI 
MENU 1, 4,1, "Copy "SI 
MENU 1,5,1, "Delete n A D"S 
MENU 1, 6, 1, "Correction A K"S 



MENU 2,0,0, ' 
MENU 2,1,1, ' 
MENU 2,2,1,' 
MENU 2,3,1, ' 
MENU 2,4,1," 
MENU 2,5,1, ' 
MENU 2,6,1, ' 
MENU 2,7,1/ 
MENU 2,8,1," 
MENU 2,9,1, ' 
MENU 2,10,1, 
MENU 2,11,1, 



'Body 

'Plane 

'Triangle 

'Parallelogram 

'Circle 

'Circle segment 

'Arc 

'Sphere 

'Cylinder 

'Cylinder seg. 

"Cone 

"Spheroid 



MENU 3,0,0, "Disk "SI 

MENU 3, 1,1, "Load Lisf'SI 
MENU 3, 2,1, "Load Mat "SI 



338 



Abacus Appendix C — The Editor Program 



MENU 3,3,l,"Save List'"!! 

MENU 3, 4,1, "Save Mat "SI 

SI 

MENU 4, 0,0, "Operations "SI 

MENU 4,1,1, "Left L"SI 

MENU 4,2,1, "Right R"SI 

MENU 4, 3,1, "Segment "SI 

MENU 4, 4, 1, "Factor "SI 

MENU 4, 5,1, "Fact or* 2 *"SI 

MENU 4, 6,1, "Factor/2 /"SI 

MENU 4, 7,1, "Mat. editor "SI 

MENU 4, 8,1, "Refresh A R n< I 

MENU 4, 9,1, "Show S"SI 

MENU 4,10, 1, "Lines "SI 

MENU 4,11,1, "Quit "SI 

CALL lazymouseSI 
END SUBSI 
SI 

SUB akt5 STAT1CSI 
'TASK ractivate Menu 5SI 

CALL busymouse SI 

MENU 5, 0, 1, "Mat. editor "SI 

MENU 5,l,l,"Left L"Sl 

MENU 5,2, 1, "Right R"SI 

MENU 5, 3, 1, "Delete A D"Sl 

MENU 5, 4, 1, "Correction"K"Sl 

MENU 5, 5, 1, "Material M"SI 

MENU 5, 6,1, "Quit "SI 

CALL lazymouseSI 
END SUB SI 
SI 

SUB deactivS STATIC^ 
'TASK :deactivate Menu 5 SI 

CALL busymouse SI 

MENU 5, 0, 0, "Mat. editor "SI 

MENU 5, 1,0, "Left L"SI 

MENU 5, 2,0, "Right R"SI 

MENU 5, 3, 0, "Delete A D"SI 

MENU 5, 4, 0, "Correction^K"SI 

MENU 5, 5, 0, "Material M"SI 

MENU 5, 6, 0, "Quit "SI 

CALL lazymouseSI 
END SUB SI 
SI 

*********************CT 

** MATERIAL-EDITOR **SI 

IJB mateddy STATICSI 

TASK -.configure window for material editorSl 

SHARED matpt r, mat, nrl%, nr2% , nr3%, nr4%, n r5%, nr 6%SI 

CALL e n t a c 1 1 w i t h 4 SI 

CALL akt5SI 

mat=lSI 

WINDOW 5, "Material-Editor", (0, 85) - (314, 190) , 1 6, 1SI 

CALL showmat (matpt r) SI 

CALL deletegadget (nrl%) 'active gadget must, be deact ivatedS 

CALL deletegadget (nr2%) SI 

CALL deletegadget (nr3%) SI 

CALL deletegadget (nr4%) SI 

CALL deletegadget (nr5%) SI 

CALL deletegadget (nr6%) SI 
END SUBSI 



339 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



f 

SUB newmat (matptr) STATICf 

'TASK : See corresponding routine for the body listf 
SHARED mat free, mat! (),matnumf 
IF matfree<matnum THENf 
mat ptr=matf reef 
matfree=mat! (matptr,!) SI 
mat! (matptr, 0) -Of 
mat! (matptr, l)=0f 
END IF f 
END SUBf 
f 

SUB finishmat STATICf 

"TASK : See corresponding routine for the body list SI 
SHARED mat,gadget% ()f 

WINDOW 6," QUIT ", (0, 129) - (314, 150) , 0, If 
PRINT "Really ? "f 

CALL initgadget (110,3,15, 30, 1, 6, nrl%, 100, -1 ) SI 
CALL initgadget (160,3,15, 60, 1 , 6, nr2%, 200, -1) SI 
WHILE gadget% (nrl%, 4)><0 AND gadget% (nr2%, 4 ) ><0SI 
WENDS1 

IF gadget %(nrl%, 4) =0 THENSI 
mat=0f 

WINDOW CLOSE 5 SI 
WINDOW CLOSE 6SI 
CALL deactiv5SI 
CALL actlwith4f 
PALETTE 2,0, 0, Of 
ELSESI 

WINDOW CLOSE 6 SI 
END IFSI 

CALL deletegadget (nrl%)f 
CALL deletegadget (nr2%) SI 
END SUBSI 
SI 

SUB deleter mac (matptr) STATICf 

"TASK :See corresponding routine for the body list SI 
SHARED mat ! ( ) , mat f reef 
IF matptrxO THENf 
FOR i=0 TO 6f 

mat ! (matptr, i ) =0f 
NEXT i f 
mat! (matptr, 0)=- If 
mat! (matptr, l)=matf reef 
mat f ree=matptrf 
CALL leftsmat (matptr) f 
END IF f 
END SUBf 
f 

SUB leftsmat (matptr) STATICf 

'TASK : See corresponding routine for the body listf 
SHARED mat! () ,nrl%, nr2%, nr3%,nr4%, nr5%, nr6%f 
IF matptrxO THEN f 

matptr=matptr-lf 
END IFf 
WHILE mat! (matptr, 0) =-lf 

matptr=matptr-lf 
WENDf 

CALL showmat (matptr) f 
CALL deletegadget (nrl%)f 
CALL deletegadget (nr2%) f 
CALL deletegadget (nr3%)f 



340 



Abacus Appendix C — The Editor Program 



CALL deletegadget (nr4%)! 
CALL deletegadget (nr5%) 5 
CALL deletegadget (nr6%) ! 
END SUB ! 

! 
SUB rightsmat (matptr) STATIC! 

'TASK : See corresponding routine for the body list SI 
SHARED mat! ( ) , matnum, nrl%, nr2%, nr3%, nr4%, nr5%, nr 6%! 
old=matptr! 
IF matptr<matnum THEN! 

matptr=matptr+l! 
END IF! 
WHILE mat ! (matptr, 0) =-1 AND matptr<matnum! 

matptr=matptr+l! 
WEND! 
IF mat! (matptr, 0) =-1 THEN! 

matptr=old ! 
ELSE! 

CALL showmat (matptr) ! 
CALL deletegadget (nrl%)! 
CALL deletegadget (nr2%)! 
CALL deletegadget (nr3%) ! 
CALL deletegadget (nr4%)! 
CALL deletegadget (nr5%)! 
CALL deletegadget (nr 6%) SI 
END IF! 
END SUB! 
! 

SUB mat input (matptr) STATIC! 

'TASK : See corresponding routine for the body list! 
SHARED mat ! ( ) ! 
CALL newmat (matptr) ! 
CALL getmat (matptr) ! 
END SUB! 
! 

SUB getmat (matptr) STATIC! 

'TASK : see corresponding routine for the body list! 
SHARED mat! () , gadget% () , nrl%, nr2%, r.r3%, nr4%, nr5%, nr 6%! 
CALL showmat (matptr) ! 
WHILE gadget%(nr6%, 4)><0! 

PALETTE 2,gadget% (nrl%, 4) /100,gadget% (nr2%, 4) /100, gadget % (nr3% , 4 ) /100! 
WEND ! 

mat! (matptr, 0)=gadget% (nrl%, 4) /101! 
mat! (matptr, l)=gadget% (nr2%, 4) /I 01! 
mat! (matptr, 2) =gadget% (nr3%, 4) /101! 
mat! (matptr, 3) =gadget% (nr4%,4) /101! 
mat! (matptr, 4 ) -gadget % (nr5%, 4) /101! 
CALL deletegadget (nrl%) ! 
CALL deletegadget (nr2%)! 
CALL deletegadget (nr3%)! 
CALL deletegadget (nr4%)! 
CALL deletegadget (nr5%)! 
CALL deletegadget (nr6%)! 
END SUB ! 
! 

SUB showmat (matptr) STATIC! 

'TASK :See corresponding routine for the body list! 
SHARED mat! ( ) , nrl%, nr2%, nr3%, nr4%, nr5%, nr6%! 
CLS! 

PRINT "Material:"! 
CALL put real (matptr*l ! , 1,10,10)! 
IF matptr ><0 THEN! 



341 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



LOCATE 1,2 SI 

PRINT "R+G+B="SI 

PALETTE 2, mat ! (matptr, 0) , mat ! (matptr, 1) , mat .' (matptr, 2) SI 

LINE (250,0)~(260,7) ,2,bfSI 

PRINT "Red : "SI 

PRINT f 

PRINT "Green : "SI 

PRINT SI 

PRINT "Blue : "SI 

PRINT SI 

PRINT "Shadow : "SI 

PRINT SI 

PRINT "Mirroring : "SI 

wl%=mat! (matptr, 0)*10H 

w2%=mat! (matptr, 1 ) *101SI 

w3%=mat! (matptr, 2) *101SI 

w4%=mat! (matptr, 3 ) *101SI 

w5%=mat ! (matptr, 4) *101 SI 

CALL initgadget (110, 8, 10, 102, wl%, 5, nrl%, -1, -1 ) SI 

CALL initgadget (110, 24, 10, 102, w2%, 5, nr2%, -1,-1) SI 

CALL initgadget (110, 40,10, 102, w3%, 5, nr3%, -1,-1) Si 

CALL initgadget (11 0,56, 10, 102, w4%, 5, nr4%, -1,-1) S! 

CALL initgadget (110, 72, 10, 102, w5%, 5, nr5%, -1, -1 ) SI 

CALL initgadget (110, 88, 15, 30, 1 , 5, nr6%, 0, -1 ) SI 
END IFSI 
END SUBSI 
SI 
• ***•*■***■*****•*•(]{ 

'** GADGETS **SI 

SUB checkgadget STATICSI 

'TASK :test whether a. gadget has been clicked SI 
SHARED gadget % () , gadget s% SI 
dummy-MOUSE (0) SI 
ax -MOUSE (3) 'Mouse positionSI 
ay=MOUSE(4) SI 
i=0SI 

WHILE i<=10 'search entire arraySI 
x%=gadget% (i , 0) 'get values from array SI 
y%=gadget% (i,l)SI 
h%=gadget%(i,2)SI 
l%=gadget% (i,3)SI 
valu%=gadget%(i, 4) SI 
wi nd%=gadget % ( i , 5 ) SI 
yes%=gadget% (i, 6) SI 

none%=gadget% (i, 7) 'Mouse over gadget ?SI 

IF x%<ax AND x%+l%>ax AND y%<ay AND y%+h%>ay AND x%>-0 AND WINDOW (0) =-wind% THENSl 
old=WINDOW (1 ) 'reserve output window^ 

WINDOW OUTPUT wind% 'delete old slider draw new oneSI 
IF yes%=-l THENSl 

LINE (valu%+x%+l,y%+l)- (valu%+x%+l , y% + h%-l ) , 0SI 
valu%=ax-x%-lSI 

LINE (valu%+x%+l,y%+l)-(valu%+x%+l,y%+h%-l) , 3SI 
gadget % (i, 4) =valu% 'get new valueSI 
ELSESI 

IF none%=-l THENSl 

IF valu%=l THEN 'first time, invert itSI 
gadget%(i,4)=0SI 

LINE <x%,y%)-(x%+l%,y%+h%) ,0,bfSI 
PUT (x%,y%) , gadget s% (ye s%), PRESETS! 
ELSE SI 

gadget % (i, 4) =1 'else return SI 



342 



Abacus Appendix C — The Editor Program 



LINE (x%,y%)-(x%+l%,y%+h%),0,bffl 
PUT (x%,y%), gadget s% (yes%)3l 
END IFfl 
ELSE f 

IF valu%=l THEN 'first time, display no outputs 
gadget%(i,4)=0SI 

LINE (x%,y%)-(x%+l%,y%+h%) , 0,bfS! 
PUT (x%,y%) ,gadgets%(none%)5 
ELSE f 

gadget%(i, 4) =1 'else yes output <3I 
LINE (x%,y%)-(x%+l%,y%+h%) ,0,bff 
PUT (x%,y%),gadgets%(yes%)SI 
END IFf 
END IFfl 
END IFfl 

WINDOW OUTPUT old 'old output window active^ 
i=10 <5L 
END IFfl 
i=i+lfl 
WENDSI 
END SUB f 
1 

SUB initgadget (x%,y%,h%, 1%, valu%,wind%, nr%,yes%, none%) STATICSI 
TASK .-place a new gadget in the gadget array gadget%()5 
PARAMETER: =>x%,y% Position of upper left corner^ 
h%,l% border height and lenghtSI 
valu% Start valued 
wind% Output window^ 
yes%,none% if yes%=-l,then sliderl 

if none%=-l, gadgets inverts when clicked^ 
else display another gadgets 

yes% and none% supply the indices for graphic information^ 
of the array gadgets f 
<=nr% Position of the gadgets in array f 
SHARED gadget %() , gadgets % () SI 

IF x%>=0 AND y%>=0 AND h%>=2 AND 1%> = 3 AND valu%> = AND valu%<l% AND wi.:d%>0 
THENSI 

MOUSE OFF SI 
old=WINDOW(l)SI 
WINDOW OUTPUT wind%SI 
IF yes%=-l THENSI 

LINE (x%,y%)-(x%,y%+h%)H 
LINE -(x%+l%,y%+h%)l 
LINE -(x%+l%,y%)SI 
LINE -(x%,y%)5 

LINE (valu%+x%+l,y%+l)-(valu%+x%+l,y%+h%-l) ,31 
ELSEf 

IF valu%=l THENf 

PUT (x%,y%),gadgets%(yes%)SI 
ELSESI 

PUT (x%,y%),gadgets%(none%)SI 
END IFSI 
END IFSI 
nr%=0fl 
WHILE gadget! (nr%,0)x-l AND nr%<=9 SI 

nr%=nr%+lSI 
WEND5 

IF gadget! (nr%,0)=-l THEN f 
gadget% (nr!,0)=x!fl 
gadget! (nr!,l)=y!Sl 
gadget! (nr!, 2 )=h!SI 
gadget% (nr!,3)=l!S[ 



343 



Appendix C — The Editor Program Amiga 3D Graphic Programming 



gadget%(nr%, 4)=valu%! 
gadget% (nr%, 5) =wind%! 
gadget% (nr%, 6) =yes%! 
gadget% (nr%, 7) =none%! 
END IF ! 
MOUSE ON! 

WINDOW OUTPUT old! 
END IF! 
END SUB! 

! 
SUB deletegadget (i) STATIC! 
■TASK -.delete a gadgets 

' PARAMETER :=>i Index of gadgets in array ! 
SHARED gadget%()! 
IF i>=0 AND i<=10 THEN! 

gadget% (i, 0)=-lf 
END IF! 
END SUB ! 

! 

« ••••••••••••••••••ci 

' ** MOUSE POINTER* *! 
i ••••••••••••••••••cr 

! 

SUB busymouse STATIC! 

'TASK :the mouse pointer in busy mode! 

SHARED buffers SI 

FOR i=l TO 41 

WINDOW OUTPUT i! 

CALL setpointer& (WINDOW (7) .buffers, 15, 16, -8, -7) 1 

NEXT i ! 
END SUB! 
! 

SUB lazymouse STATIC! 
'TASK rChange mouse pointer to cross hair! 

SHARED buffer&fl 

FOR i=l TO 4! 

WINDOW OUTPUT i! 

CALL setpointer& (WINDOW (7) , buf fer&+68, 15, 16, -8, -7) SI 

NEXT i! 
END SUB! 
! 

SUB initmaus STATIC! 
'TASK : save two mouse pointers! 

SHARED buffers! 
mousedata: ! 

DATA 0,0! 

DATA 0, 1, 0, =32767, 0,-18751, 0,-1, 0,-18751, 0,-32767! 

DATA 14016,-32767, 14016,-14017, 14016,-32767, 0,-32767! 

DATA 13848,-18919, 13848,-1, 13848,-18919, 0,-32767, 0! 

DATA -32767! 

DATA 0, 0! 

DATA 0,0! 

DATA 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0! 

DATA -258, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0, 256, 0! 

DATA 256, 0! 

DATA 0,0! 

RESTORE mousedata! 

FOR i=0 TO 67! 
READ valu%! 
POKEW buffer&+i*2,valu%! 

NEXT i! 
END SUB! 



344 



Abacus Appendix D — The SetPoint Program 



D. The SetPoint Program 



The SetPoint machine language program used by the tracer program 
is listed here. The program appears here in machine language source 
code and as a BASIC loader, for those of you who do not have the 
AssemPro assembler. 

; SetPoint. ASM 

/Output one rectangle in one Rastport (screen) 

/Calculate from the existing colour word the desired combination 
; for the desired color word. 



LVOOpe nLi br a ry 


= -552 


LVOCloseLibrary 


- -414 


LVOReadPixel 


= -318 


LVORe-tFill 


= -306 


LVOSetAPen 


= -342 


LVOSetBPen 


= -348 



HAM = $800 
rp_AreaPtrn = 8 
rp_FgPen =25 
rp_BgPen =26 
rp_AreaPtSz =29 

/Offsets for the parameter of the stack: All longwords 

NumPattern = 11 

sinc=15*4 

xl=4+sinc 

yl=8+sinc 

xr=12+sinc 

yr=16+sinc 

red=22+sinc 

green=26+sinc 

blue=30+sinc 

CALLS YS : MACRO $\1 
JSR _LVO\l (A6) 

ENDM 

OpenGfx: 

/open libraries 

MOVEM.L D0/D1/A0/A1/A6,-(SP) 

MOVEQ #0,D0 
LEA GfxName,Al 
MOVE.L 4,A6 
CALLSYS OpenLibrary 
LEA Gf xBase, A0 
MOVE.L DO, (A0) 

MOVEM.L (SP)+,DQ/D1/A0/A1/A6 



345 



Appendix D — The SetPoint Program Amiga 3D Graphic Programming 

RTS 
CloseGfx: 
; close libraries 

MOVEM.L D0/D1/A0/A1/A6,-(SP) 

MOVE.L Gf xBase, DO 
BEQ.S \R 
MOVE.L D0,A1 
MOVE.L 4,A6 
CALLSYS CloseLibrary 
\R: 
MOVEM.L (SP)+,D0/Dl/A0/Al/A6 
RTS 

SetPoint: 

/output one rectangle. Parameter: 

; (xl , yl , xr , yr, red, green, blue) 

MOVEM.L D0-A6 r -(SP) 

MOVE.L Gf xBase, DO 
BEQ \R 
MOVE.L D0,A6 

MOVE Modus, DO 
ANDI #HAM, DO 
BEQ \NORMAL 
/Determine color of last pixel: 

MOVEM . L x 1 { SP ) , D / D 1 

SUBQ #1,D0 

BCC.S \HAM1 

MOVEQ #0,D0 ;If Pixel = first in line => background color 

BRA.S \HAM2 
\HAM1: 

MOVE.L RastPort,Al 

CALLSYS ReadPixel 

TST DO 

BMI \R 
\HAM2: ;D0= Color number 

;Copy additional HAM-Colors in array: 



LSL #3, DO 
LEA Colour, AO 
LEA 2(A0,D0) ,A1 
MOVEM (A1),D3-D5 
ADD #128, AO 



A oldcolor 

red, green, blue 

Start the list for HAM-Colors: 128=16*£ 



MOVEQ #$10, Dl ;ColorNr: blue 
MOVEQ #16, DO ;16 Steps 

MOVEQ #0,D5 ;blue-lntensity=0 

BRA.S \SHIB 
\SHLB: 
MOVE Dl, (A0)+ 
ADDQ #1,D1 
MOVEM D3-D5, (AO) 



346 



Abacus 



Appendix D — The SetPoint Program 



;old blue-Intensity 
; red-lntensity=0 



: 64=1024/16 



;ColorNr=$30! :Green 



ADDQ.L #6,A0 
ADD #64, D5 
\SHIB: 
DBRA D0,\SHLB 
MOVE 4 (Al) ,D5 

MOVEQ #0,D3 

MOVEQ #16, DO 

BRA.S \SHIR 
\SHLR: 

MOVE Dl, (A0)+ 

ADDQ #1,D1 

MOVEM D3-D5, (A0) 

ADDQ.L #6,A0 

ADD #64, D3 
\SHIR: 

DBRA D0,\SHLR 

MOVE <A1)+,D3 

MOVEQ #16, DO 

MOVEQ #0,D4 

BRA.S \SHIG 
\SHLG: 

MOVE Dl, (A0)+ 

ADDQ #1,D1 

MOVEM D3-D5, (A0) 

ADDQ.L #6,A0 

ADD #64, D4 
\SHIG: 

DBRA D0,\SHLG 



;Now all 64 possible colors are calculated => all normal 
; additional . 

\ NORMAL: 

;Seacrh first for the color, in one pass: 

LEA Colour, A0 
MOVE MaxColour,D0 
MOVEQ #-l,D7 /Minimum 

MOVE.L A0,A1 
BRA.S \IN1 
\LP1: 

MOVE 2 (A0) ,D1 
SUB red(SP) , Dl 
MULS D1,D1 
MOVE 4(A0) ,D2 
SUB green (SP) ,D2 
MULS D2,D2 
ADD.L D2,D1 
MOVE 6{A0),D2 
SUB blue(SP) ,D2 
MULS D2,D2 
ADD.L D2,D1 

CMP.L D1,D7 
BLS.S \NXT1 

MOVE.L Dl,D7 

MOVE.L A0,A1 



347 



Appendix D — The SetPoint Program Amiga 3D Graphic Programming 



\NXT1 : 

ADDQ.L #8,A0 
\IN1: 

D3RA D0,\LP1 

Search now the color, in the second pass: 

LEA Colour, AO 
MOVE MaxColour,DO 
MOVEQ #-l,D7 ; Minimum 

MOVE.L A0,A2 
BRA.S \IN2 
\LP2: 

BSR \COMPARE_Colour 
BEQ.S \NXT2 

MOVE 2 (AO) ,D1 
SUB red(SP) , Dl 
MULS D1,D1 
MOVE 4 (AO) , D2 
SUB green (SP) ,D2 
MULS D2,D2 
ADD.L D2,D1 
MOVE 6 (AO) ,D2 
SUB blue(SP) , D2 
MULS D2,D2 
ADD.L D2,D1 

CMP.L Dl,D7 
BLS.S \NXT2 

MOVE.L Dl,D7 

MOVE.L A0,A2 

\NXT2 : 

ADDQ.L #8,A0 
\IN2: 

DBRA DO, \LP2 

/Search pattern for optimal approximation: 

BSR.S \ SEARCH PATTERN 
MOVE.L D7,D3 
MOVE.L A3,A4 

;Is equal again with inverse Pattern: 

EXG A1,A2 BSR.S \ SEARCH PATTERN 
CMP.L D3,D7 
BLO.S \RECT 

EXG Al,A2 MOVE.L A4,A3 ;Old value was better! 

\RECT: 

;A1 A ColorNrl, A2 A ColorNr2, A3 A Pattern 

MOVE (A1),D7 

MOVE (A2),D0 

MOVE . L R a s t P o r t , Al 

MOVE . L A3 , rp_AreaPt rn ( Al ) 

MOVE. 3 #4,rp_AreaPtSz(Al) 

MOVE.L A1,-(SP) 

CALLS YS SetAPen 



348 



Abacus 



Appendix D — The SetPoint Program 



MOVE.L (SP),A1 
MOVE 07,00 
CALLSYS SetBPen 
MOVE.L (SP)+,Al 

/Clipping: 

MOVEM.L xl (SP) ,D0-D3 

MOVEM RasterWl,D4/D5 

CMP 04,00 

BHI.S \R 

CMP 05,01 

BHI.S \R 

CMP D4,D2 

BLS.S \R1 

MOVE 04,02 
\R1: 

CMP D5,D3 

BLS.S \R2 

MOVE 05,03 
\R2: 

CALLSYS RectFill 

\R: 
MOVEM.L (SP)+,D0-A6 
RTS 

\SEARCH_PATTERN: 

;A1 A Colorl, A2 A Color2. => A3 A Pattern. 

LEA PATTERN, AO 
LEA 2 (AO) ,A3 
MOVEQ #-l,D7 
MOVEQ #NumPattern-l,DO 
\LPM: 

MOVE (A0),D1 

MOVE #1024,02 

SUB 01,02 ;l-BkgkPattern 



MOVE 2(A1) ,06 

BEQ.S \E1 

MULU D2,D6 

DIVU #1024,06 
\E1: 

MOVE 2 (A2 ) , 05 

BEQ.S \E2 

MULU 01, D5 

DIVU #1024, D5 
\E2: 

ADD D5,D6 

SUB red+4 (SP) ,06 

MULS D6,D6 

MOVE 4 (Al) ,04 
BEQ.S \E3 
MULU 02, D4 
DIVU #1024, 04 
\E3: 

MOVE 4 (A2 ) , D5 
BEQ.S \E4 
MULU 01, D5 



; Colorl. red* (1-BkgnPattern) 



;Color2.red*BkgnPattern 



; Color . red 
; Difference 
;The guadrant 



; Colorl. green* (1-BkgnPattern) 



; Color2 . green*BkgnPattern 



349 



Appendix D — The SetPoint Program Amiga 3D Graphic Programming 



DIVU #1024, D5 
\E4: 

ADD D5,D4 ; Col or. green 

SUB green+4 (SP) , D4 
MULS D4,D4 
ADD.L D4,D6 

MOVE 6(A1) , D4 

BEQ.S \E5 

MULU D2,D4 ;Colorl .blue* (1-BkgnPattern) 

DIVU #1024, D4 
\E5: 

MOVE 6 (A2) ,D5 

BEQ.S \E6 

MULU Dl,D5 ;Color2.blue*BkgnPattern 

DIVU #1024, D5 
\E6: 

ADD D5,D4 ; Color. blue 

SUB blue+4 (SP) ,D4 

MULS D4,D4 

ADD.L D4,D6 ; distance between desired and current Color 

CMP.L D6,D7 
BLS.S \NXTM 

LEA 2 (A0) ,A3 

MOVE.L D6,D7 

BEQ.S \FND 

\NXTM: 
ADD #34, A0 
DBRA D0,\LPM 

\FND: 
RTS 

\ COMP ARE_C o 1 o u r : 

;A1 A Colorl, A0 A Color2 

CMP.L A1,A0 
BEQ.S \CFR 
MOVE 2 (Al) ,D1 
CMP 2(A0) ,D1 
BNE.S \CFR 
MOVE 4 (Al) ,D1 
CMP 4 (A0) ,D1 
BNE.S \CFR 
MOVE 6 (Al) ,D1 
CMP 6(A0) ,D1 
\CFR: 
RTS 

GfxNamerDC.B ' graphics. library' , 

ALIGN 
G f xBase: DC. L 

RastPort:DC.L 
MaxColourrDC.W 
Modus: DC. W 
RasterWl:DC.W 320 
RasterHlrDC.W 200 



350 



Abacus Appendix D — The SetPoint Program 



PATTERN : 
DC.W 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 

DC.W 4 
DC.W $8000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 
DC.W $0000 

DC.W 8 

DC.W $8000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0080 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W 16 

DC.W $8080 

DC W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 

DC.W $0000 



351 



Appendix D — The SetPoint Program 



Amiga 3D Graphic Programming 



DC.W 
DC.W 



$0000 
$0000 



DC.W $8080 
DC.W $0000 
DC.W $0000 



DC.W 
DC.W 
DC.W 



$0000 
$0000 
$0000 



DC.W $0000 
DC.W $0000 

DC.W 32 
DC.W $8080 



DC.W 
DC.W 



$0000 
$0000 
DC.W $0000 
$0808 
$0000 



DC.W 
DC.W 
DC.W $0000 



DC.W 
DC.W 
DC.W 
DC.W 
DC.W 
DC.W 
DC.W 
DC.W 



$0000 
$8080 
$0000 
$0000 
$0000 
$0808 
$0000 
$0000 



DC.W $0000 

DC.W 64 
DC.W $8888 
DC.W $0000 
DC.W 
DC.W 



$0000 
$0000 
DC.W $8888 
DC.W $0000 



DC.W 
DC.W 
DC.W 
DC.W 



$0000 
$0000 
$8888 
$0000 



DC.W $0000 



DC.W 
DC.W 
DC.W 
DC.W 



$0000 
$8888 
$0000 
$0000 



DC.W $0000 

DC.W 128 
DC.W $8888 
DC.W $0000 
DC.W $2222 
DC.W $0000 
DC.W $8888 
DC.W $0000 
DC.W $2222 
DC.W $0000 
DC.W $8888 
DC.W $0000 
DC.W $2222 
DC.W $0000 
DC.W $8888 
DC.W $0000 



352 



Abacus Appendix D — The SetPoint Program 



DC, 


.W 


$2222 


DC, 


.w 


$0000 


DC 


.w 


256 


DC, 


.w 


$AAAA 


DC, 


.w 


$0000 


DC, 


.w 


$AAAA 


DC, 


.w 


$0000 


DC, 


.w 


$AAAA 


DC, 


.w 


$0000 


DC, 


.w 


$AAAA 


DC, 


.w 


$0000 


DC, 


.w 


$AAAA 


DC, 


.w 


$0000 


DC, 


.w 


$AAAA 


DC, 


.w 


$0000 


DC 


.w 


$AAAA 


DC 


.w 


$0000 


DC, 


.w 


$AAAA 


DC, 


.w 


$0000 


DC 


.w 


384 


DC 


.w 


$AAAA 


DC, 


.w 


$1111 


DC 


.w 


$AAAA 


DC 


.w 


$4444 


DC, 


.w 


$AAAA 


DC 


.w 


$1111 


DC, 


.w 


$AAAA 


DC, 


.w 


$4444 


DC 


.w 


$AAAA 


DC, 


.w 


$1111 


DC 


.w 


$AAAA 


DC 


.w 


$4444 


DC, 


.w 


$AAAA 


DC, 


.w 


$1111 


DC 


.w 


$AAAA 


DC 


.w 


$4444 


DC 


.w 


448 


DC 


.w 


$AAAA 


DC 


.w 


$5555 


DC 


.w 


$AAAA 


DC 


.w 


$4444 


DC, 


.w 


$AAAA 


DC, 


.w 


$5555 


DC, 


.w 


$AAAA 


DC, 


.w 


$4444 


DC, 


.w 


$AAAA 


DC, 


.w 


$5555 


DC, 


J 


$AAAA 


DC 


.w 


$4444 


DC 


.w 


$AAAA 


DC 


.w 


$5555 


DC 


.w 


$AAAA 


DC 


.w 


$4444 


DC 


.w 


512 


DC, 


.w 


$AAAA 


DC, 


.w 


$5555 


DC, 


.w 


$AAAA 


DC, 


.w 


$5555 



353 



Appendix D — The SetPoint Program 



Amiga 3D Graphic Programming 



DC.W 


$AAAA 


DC.W 


$5555 


DC.W 


$AAAA 


DC.W 


$5555 


DC.W 


$AAAA 


DC.W 


$5555 


DC.W 


$AAAA 


DC.W 


$5555 


DC.W 


$AAAA 


DC.W 


$5555 


DC.W 


$AAAA 


DC.W 


$5555 


Colour: 


DS.B 


64*8 



; ColorNr, red, green, blue 



END 

The following program is the BASIC loader used to create 
SetPoint .Bona disk named Tracer. The example program that 
follows contain some BASIC lines that must be entered on one line in 
AmigaBASIC, even though they appear on two lines in this book. 
Formatting the program listings to fit into this book has caused some 
long BASIC lines to be split into two lines. To show where a BASIC 
line is actually ended, a H will be used. This is not to be entered, it 
only shows when the <Return> key should be pressed in the BASIC 
editor. 



' SetPoint. BASSI 

OPEN "tracer: SetPoint. B" FOR OUTPUT AS 15 

FOR i=l TO 15281 

READ a$5 

a%=VAL("&H'M-a$)5 

PRINT # i , CHR$ { a % ) ; 5 

NEXT 5 
CLOSE 15 
KILL "Tracer: SetPoint. B.info"5 



datas:5 

DATA 48,E7,C0,C2, 70,0 
DATA 2,5E,20,80,4C,DF 
DATA 22,40,20,78,0,4, 
DATA 20,3A,2,34, 67,0, 
DATA 0,80, 4C,EF, 0,3,0 
DATA 4E,AE,FE,C2,4A, 4 
DATA 4C,91, 0,38, DO, FC 
DATA 48, 90,0, 38, 5C, 88 
DATA 70,10, 60, E, 30, CI 
DATA FF,F0,36,19,70,1 
DATA D8,7C,0,40,5i,C8 
DATA 60, 2C, 32, 28, 0,2 
DATA C5,C2,D2,82,34,2 
DATA 2E, 1,22, 48, 50, 88 
DATA 24,48, 60,32,61,0 
DATA 34,28,0,4,94, 6F, 
DATA C5,C2,D2,82,BE,8 
DATA 26,7,28,4B,C5,49 
DATA 22,7A,1,C,23,4B 
DATA 22,57,30,7,4E,AE 
DATA 0,EE,B0, 44, 62,14 



, 43, FA, 2, 58, 2C, 78, 0, 4, 4E, AE, FD, D8, 41, FAS! 
, 43,3,4E, 75,48,E7,O0,C2,20,3A,2,4E,67,A5 
4E, AE,FE, 62, 4C,DF, 43, 3, 4E,75, 48,E7,FF,FE5 
1, 68, 2C, 40, 30, 3A, 2, 34, 2, 40, 8, 0,67, 05 
, 40, 53, 40, 64, 4, 70,0, 60, E, 22, 7A, 2,14S[ 
0,6B, 0,1,3E,E7,48,41,FA, 3, 86, 43,F0, 0, 25 
, 0,80, 72, 10, 70, 10, 7A, 0, 60, E, 30, CI, 52, 415 
,DA,7C,0,40,51,C8,FF,F0,3A,29,0,4,76,05 
,52,41,48,90,0,38,5C,88,D6, 7C, 0, 40, 51,C85 
0,78,0,60,E,30,C1,52,41,48,90,0,38,5C,885 
,FF,F0,41,FA,3,26,30,3A, 1, A4, 7E,FF, 22, 485 
92, 6F,0,52,C3,C1,34,28,0,4,94,6F,0,5 65 
8,0,6,94,6F,0,5A,C5,C2,D2,82,BE,81, 63,45 
,51,C8,FF,D2,41,FA,2,E8,30,3A,1,66, 7E,FF5 
,1,20,67,2A,32,28,0,2,92,6F,0,52,C3,C15 
0,56,C5,C2,D2,82,34,28,0,6,94,6F,0,5A5 
1, 63,4,2E,1,24,4 8,50,88,51,C8,FF,CC,61,5C5 
,61,54,BE,83,65,4,C5,4 9,26,4C,3E,11,30,125 
0,8,13,7C,0,4,0,1D,2F,9,4E,AE,FE,AA5 
FE,A4,22,5F,4C,EF,0,F,0,40,4C,BA, 0,305 
B2, 45, 62, 10, 84,4 4,63, 2, 34, 4, B6, 45, 63, 25 



354 



A B AC US A PP EN MX l> ~— T I U SK T V i H>T P k ( h , 



DATA 36,5, 4E, AE,FE,CE, 4C, DF, 7F,FF, 4E, 75, 41,F'7A, 0, DO, 47, F.8, ,'; 

DATA 7E,FF,7 0,A, 32, 10, 34, 3C, 4, 0, 94, 41,3C, 7 9,0,2, 67, 6,CC,C2 ! 

DATA 8C,FC, 4, 0, 3A, 2A, 0, 2, 67, 6, CA,C1, 3A,FC, 4, 0, DC, 45, 9€, 67f 

DATA 0, 5 6, CD, C 6, 38,2 9,0,4,67, 6, C8, C2, 88 , FC, 4 , 0, 3A, 2A ( C, 4f 

DATA 67, 6,CA,CI , 8A,FC, 4, C,D8,45, 98, 6F, 0, 5A,C9,C4, DC, 84, 3c, 

DATA 0, 6,6" 7 , 6,C8,C2,88,FC,4,0,3A,2A,0, 6,67, 6,CA,C1, 8A,F7f 

DATA 4,0,D8, 45,98, 6F, 0, 5E, C9, C4 , DC, 84, BE, : ; c,63,8, 4 CFV',0, 7 

DATA 2E,6,67,8,D0,FC,0,22,51,C8,FF,82,4E, 75,B1,C9, 67, 1C, 3/ 

DATA 0,2,B2,68,0,2,66,12,32,2 9,0,4,B2,63,0,4, 66, 8, 32, 2 Of 

DATA 0, 6,32, 68, 0, G^E,"^, 67, 72,61 , 70, 68, 69, 63,73,7-, 6C, 6 9, 

DATA 72, 61,72, 7 9,0,0,0,0,0,0, 0,0,0, 0,0,0, 0, 0,1,4 0$ 

DATA 0,C8,G,0,0,0,C,C,0,0,Q,0,0,0,0,0,0,0,0,Of 

DATA 0,0,0,0,0, 0, 0,0, 0,0,0,0,0,0,0,0,0, 4, 80, Of 

DATA 0,0, 0,0,0,0, 0,0, 0,0, 0,0, 0,0,0,0, 0,0,0, Of 

DATA 0,0, 0,0, 0,0, 0,0, 0,0, 0,8, 80,0,0,0,0,0/, 01 

DATA 0,0, 0,0, 0,0, 0,0, 0,80, 0,0, 0,0, 0,0, 0,0, 0,01! 

DATA 0,0, 0,0, 0,10, 8 0,80, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0,0,80, 8G,0,Q,0,0,0,0,0,0,0,0,0,0,C,0,0,20f 

DATA 80,80,0, 0, 0,0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 80, 80, 0, Of 

DATA 0,0,0,0,8,8,0, 0, 0,0,0,0,0,40, 88, 88, 0, 0, 0, Of 

DATA 0, 0, 88, 88, 0,0, 0,0, 0,0, 88, 88, 0,0, 0,0, 0,0, 88, 88f 

DATA 0,0, 0,0, 0,0, 0,80, 88, 88, 0,0, 22, 22, 0,0, 88, 88,0, Of 

DATA 22, 22, 0, 0, 88, 88, 0, 0, 22, 22, 0, 0, 88, 88, 0, 0, 22, 22, 0, Of 

DATA 1,0, AA, AA, 0, 0, AA, AA, 0, 0, AA, AA, 0,0,AA,AA, 0, 0, AA,AAf 

DATA 0, 0, AA, AA, 0, 0, AA, AA, 0, 0, AA, AA, 0, 0, 1, 80, AA, AA, 1 1, Elf 

DATA AA, AA, 44,44, AA, AA, 11 , 11 , AA, AA, 44, 44, AA, AA, .1 1 , 11 , AA, AA 

DATA AA,AA, 11, 11, AA,AA, 44,44, 1 , CO, AA, AA, 55, 55,AA,AA, 44, 44 

DATA 55,55,AA, AA, 44, 44, AA, AA,55, 55,AA,AA, 44, 44, AA, AA, 55,5b 

DATA 4 4,4 4, 2, 0, AA.,AA, 55 , 55, AA, AA, 55, 55, AA,AA, 55, 55, AA,AA, 3 

DATA AA,AA,55,55,AA,AA,55,55,AA,AA,55,55,AA,AA,55, 55,0,0,0 

DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Of 

DATA 0,0, 0,0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0, 0, 0,0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0, 0,0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0,0,0,0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0, 0, 0,0,0, 0,0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0,0, 0,0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0, 0, 0,0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0, 0, 0, 0, 0, 0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0f 

DATA 0,0,0,0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA f f f f r Q f f f 0,0 r f f f f f f f t Q,Gf 

DATA 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0,0,0,0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, 0,0,0, Of 

DATA 0, 0,0, 0, 0,0,0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA , , , , , , , , , , , , , , , , , , , Of 

DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, Of 

DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0f 

DATA 0,0, 0,0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, Of 

DATA 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0,0, Of 

DATA 0, 0, 0,0,0, 0,0, Of 



\ppendix E — Tracer Error Messages Amiga 3D Graphic Programming 



E. Tracer Error Messages 



While the program is running, different errors can occur. The most 
frequent error is an input/output error, which arises when, for example, 
you try to access a nonexistent file, or when the disk has a read/write 
error. 

Such errors are processed in the tracer routine ErrorHandling. 
Also, when the modules are merged incorrectly, errors are handled in 
this routine. 

Errors occuring during the transfer of IFF graphics to and from disk arc 
not processed by this routine. ErrorHandling is activated by ON 

ERROR. 

ScreenLoad and ScreenSave use the library commands to access 
the disk. Errors such as a full disk are trapped in these routines that (for 
example, . . -Chunk cannot be saved! ! !) allow you to return 
to the program. 

Error messages when starting the program (No free Chip 
mem! ! ! ) are caused by insufficient memory. Here little tricks, like 
working with a very small AmigaDOS window help. You must also 
close or delete less important programs running in the background. 
Unfortunately it can also happen that the computer or AmigaBASIC 
will ignore the lack of memory. This can occur with a large k array 
(200+ elements) on a 512K machine. 

Errors can also be encountered during the initilization of the shadowing 
process: When the basis of an object is not a basis at all, you are 
informed. (A basis consists of three independent, linear vectors. A 
vector is not presented as a multiple of the other two vectors). These 
errors occur when the vectors a, b, and c span no space of an ellipsoid, 
cone, or cylinder or when they are coplanar or colinear. 

When you present one of the three vectors by using the other two 
vectors (for example a = x*b + y*c), only one plane or one line and no 
space is spanned causing an error. 



356 



Index 



A 




Error messages 


356 


AC/BASIC compiler 


193 


Exiting tracer program 


159 


Addition theorem 


55 


F 




Algorithm 


10,167,179 




AmigaBASIC 


19,193 


File manipulation 


154 


Angles 


184 






Arc 


17,149 


G 




ASCII format 


51 


Gadgets 


77 


B 




Graph paper 


173 


B-splines 


167 


H 




Background 


73,157 


HAM mode 


40,173 


Bezier 


167 


Hardcopy 


117 


Brightness 


9 


Hidden line algorithms 


7 


c 




Hidden surface algorithms 


7 


Cartesian coordinates 


45,58 


i 




Circle 


13,148 


Interchange File Format ( 


[FT! J 14,1 17, 


Color 


10,173 




169,193 


Compiling 


194 


Intersection point 


22,187 


Components 


181 






Cone 


14,151 


K 




Coordinates 
Cosine 


12,181 

53 


Keyboard shortcuts 


126,163 


Cray 


48 






Cylinder 


14,150 


L 




D 




Light rays 


9 




Light source 


8,161,170,174 


Data structure 
Determinant 


16 
23,188 


Loading Materials 


157 


Difference vectors 


179 


M 




Direction vector 


37 






Display 


11 


Main point 
Material editor 


52 
152 


E 




Memory management 


93 




Menus 


84 


Editor 


74-75,145-159, 


Modules 


75 




167,179,302-344 


Multiple light sources 


170 


Editor data manipulation 94 






Editor instructions 


145-159 


o 




Editor sample run 
Ellipsoid 
Enhanced objects 
Enlargement 
Equal vectors 


78 

14 

167 

58,94,160,174 

179 


Object data 
Object rotation 
Objects 
Optimization 
Optional disk 


146 

168 

7,146,167 

44 

78,193 



3 57 



iXDr 



Amiga 3D Graphic Programming 



p 




V 




Parallelogram 


11,148 


Vectors 


22,179 


Perception 


19 


Visual rays 


9 


Perpendicular 


13 






Perspective 


55 


w 




Pixc 1 size 


161 


Wire model 


51,104,160,174 


Plane 


8,161,174 
11,147,182 


Word processor 


74 


PI an rung graphics 


173 


X 




Point of view 
Polar coordinates 


174 
14 


X coordinate 


51 


timing graphics 


158 


Y 




Projection point 
Pythagorean theor 


22,174 

ens 185 


Y coordinate 


51 


R 

Ray tracer |)K»grun 


t 'Yv Tracer 


z 

Z coordinate 


51 


Ray ?r icinti 


1 






Say tracing algon 


li:IU:% / 






Rectangle 


22,160 






Recursion 


10 






Reference poini 


94 






Reflection 


9 






Requester 


131 






Resolution 


173 






Rotation 


52,55 






s 








Saving graphics 


158 






Scalar 


22 






SciPoim program 


193,345-355 






Shading 


173 






Shadow 


7,160 






ShowlLBM pre ly- 


mi 193 






sine 


53 






Smooth shading 


168 






Sphere 


14,150,182 






Spheroid 


151 






T 








Tangent 


53 






Tracer 


19,104,1 19,145-163 

,167,179,207-301 






Tracer inMtiH liuib 


155-163 






Tracer menus 


155-163 






Tracer modules 


203-206 






Transparent;) 


10,169 






Triangle 


7,147,167 






Tricks and lips 


173 






Two dimensional i 


, tvjeets 14 







358 



Optional Diskette Offer 









































































AMIGA 




3D Graphic 

Programming 

in BASIC 




Optional diskette 









For your convenience, the program listings contained in this book are available on an 
Amiga format floppy disk. You should order the diskette if you want to use the programs, 
but don't want to type them in from the listings in the book. 

The optional diskette for Amiga 3D Graphic Programming in BASIC includes 
BASIC source code for the editor program, ASCII sources of the tracer program modules, 
and compiled > ready to run versions of the tracer and editor programs. Also included are a set 
of 3D wire model graphics and their matching materials, ready for calculation. 

All programs on the diskette have been fully tested. You can change the programs to suit 
your particular needs. The diskette is available for $14.95 plus $2.00 ($5.00 foreign) for 
shipping and handling. 

When ordering by mail, please give your name and shipping address. Enclose a check, 
money order or credit card information. Mail your order to: 



Abacus 



5370 52nd Street SE 
Grand Rapids, MI 49508 

Or for fast service (credit card orders only) 

call 616-698-0330 (orders within Michigan) 

or 1-800-451-4319 (orders outside of Michigan). 



One Good Book deserves another 
and another, and another, 



^ e Amiga C' 

for Advanced 
Programmers 



Ne* ! 

Amiga C 

for Beginners 



»«a 



,ga 3D Graphics 
Programming 
in BASIC 




Amiga Disk Drives 
Inside A Out 



Amiga C for Advanced Programmers 

■contains a wealth of information from the pros: how compil- 
ers, assemblers and linkers work, designing and program- 
ming user friendly interfaces using Intuition, combining 
assembly language and C codes, and more. Includes com- 
plete source code for text editor. 
ISBN 1-55755-046-8 $24.95 

Amiga C for Beginners 

-an introduction to learning the popular C language. Explains 
the language elements using examples specifically geared 
to the Amiga Describes C library routines, how the compiler 
works and more. 
ISBN1-55755-045-X $19.95 



Amiga 3-D Graphic Programming in BASIC 

-shows you how to use the powerful graphic capabilities of 
the Amiga Details the techniques and algorithms for writing 
three-dimensional graphic programs: ray tracing in all reso- 
lutions, light sources and shading, saving graphics in IFF 
format and more 
ISBN 1-55755-044-1 $19.95 

Amiga Disk Drives Inside & Out 

-is the most in-depth reference available covering the Amiga's 
disk drives Learn how to speed up data transfer, how copy 
protection works, computer viruses, Workbench and the CLI 
DOS functions, loading, saving, sequential and random file 
organization, more. 
ISBN1 -55755-042-5 $29.95 



AmigaDOS Inside and Out 

-covers the insides of AmigaDOS from the internal design up 
to practical applications. Includes detailed reference sec- 
tion, tasks and handling, DOS editors ED and EDIT, how to 
create and use script files, multitasking, and much more. 
ISBN 1-55755-041-7 $19.95 

Includes Workbench 1.3 

Amiga Machine Language 

-is a comprehensive introduction to 68000 assembler ma- 
chine language programming and is THE practical guide for 
learning to program the Amiga in ultra-fast ML. Also covers 
68000 microprocessor address modes and architecture, 
speech and sound from ML and much more. 
ISBN 1-55755-025-5 $19.95 

Amiga System Programmer's Guide 

-comprehensive guide to what goes on inside the Amiga in 
a single volume. Only a few of the many subjects covered 
include the EXEC structure, I/O requests, interrupts and 
resource management, multitasking functions and much, 
much more. 
ISBN 1-55755-034-4 $34.95 

AmigaDOS Quick Reference * 

-an easy-to-use reference tool for beginners and advanced 
programmers alike. You can quickly find commands for your 
Amiga by using the three handy indexes designed with the 
user in mind. All commands are in alphabetical order for easy 
reference. Includes Workbench 1.3 
ISBN 1 -55755-049-2 $1 4.95 



AmigaDOS 
Inside & Out 



m 



Amiga 

Machine Language 



Amiga System 

Programmers Guide 



w" 



M 



' *~iigaDOS 




Amiga for 
Beginners 



se |ier'. __ 
Be s \\„,foiiL\sic 

Inside and Out 



Amiga For Beginners * 

-the first volume in our Amiga series, introduces you to 
Intuition (Amiga's graphic interface), the mouse, windows, 
the CLI and Amiga BASIC and explains every practical 
aspect of the Amiga in plain English. 
ISBN 1-55755-021-2 ^ $16.95 

Includes Workbench 1.3 

AmigaBASIC Inside and Out 

-THE definitive step-by-stepguide to programming the Amiga 
in BASIC. Every AmigaBASIC command is fully described 
and detailed. Topics include charts, windows, pulldown 
menus, files, mouse and speech commands. 
ISBN 0-916439-87-9 $24.95 

Includes Workbench 1.3 



Computer Viruses: a high-tech disease * 

-describes what a computer virus is, how viruses work, 
viruses and batch files, protecting your computer, designing 
virus proof systems and more. 
ISBN 1-55755-043-3 $18.95 



"I'mlhihlv ihc hc\i uiithi 



PC Week 11-21-S8 



COmPUTGR 

jljjj 



Optional 

Disk 



Save Time and Moneyl-Optionai program disks are avail- 
able for many of our Amiga reference books. Ail programs iisted 
in the books are on each respective disk and will save you 
countless hours of typing! $14.95 

(* Optional Diskette Not Available for these Titles) 



Amiga 

Tricks & Tips 



Amiga Tricks and Tips 

-follows our tradition of other Tricks and Tips books for CBM 
users Presents dozens of tips on accessing libraries from 
BASIC, custom character sets, AmigaDOS, sound, impor- 
tant 68000 memory locations, and much more 1 
ISBN 0-916439-88-7 $19.95 



Abacus 



Ifffffllllll 



Dept. L2, 5370 52nd Street SE 
Grand Rapids, Ml 49508 



See your local Dealer or Call Toll Free 1-800-451-4319 



Add $4.00 Shipping per Order 
Foreign add $12.00 per item 



New Software 



The Ideal Amiga wordprocessor 



TextPro 

Amiga 



TextPro Amiga upholds the true spirit of the Amiga: 
it's powerful, it has a surprising number of "extra" 
features, but it's also very easy to use. TextPro 
Amiga — the Ideal Amiga word processor that proves 
just how easy word processing can be. You can write 
your first documents immediately, with a minimum of 
learning — without even reading the manual. But 
TextPro Amiga is much more than a beginner's 
package. Ultra-fast onscreen formatting, graphic merge 
capabilities, automatic hyphenation and many more 
features make TextPro Amiga ideal for the 
professional user as well. TextPro Amiga features: 



High-speed text input and editing 

Functions accessible through menus or shortcut keys 

Fast onscreen formatting 

Automatic hyphenation 

Versatile function key assignment 

Save any section of an Amiga screen & print as text 

Loading and saving through the RS-232 interface 

Multiple tab settings 

Accepts IFF format graphics in texts 

Extremely flexible printer adaptations. Printer drivers 

for most popular dot-matrix printers included 

Includes thorough manual 

Not copy protected 

TextPro Amiga 

sets a new standard 
for word processing 
packages in its price 
range. So easy to 
use and modestly 
priced that any 
Amiga owner can 
use it — so packed 
with advanced 
features, you can't 
pass it up. 

Suggested retail price: $79.95 




All Abacus software runs on the Amiga 500, Amiga 

1000 or Amiga 2000. Each package is fully compatible 

with our other products in the Amiga line 



More than word processing... 



BeckerText 

Amiga 



This is one program for serious Amiga owners. 
BeckerText Amiga is more than a word processor. It 
has all the features of TextPro Amiga, but it also has 
features that you might not expect: 

• Fast WYSIWYG formatting 

• Calculations within a text — like having a spreadsheet 
program anytime you want it 

• Templates for calculations in columns 

• Line spacing options 

• Auto-hyphenation and Auto-indexing 

• Multiple-column printing, up to 5 columns on a single 
page 

• Online dictionary checks spelling in text as it's written 

• Spell checker for interactive proofing of documents 

• Up to 999 characters per line (with scrolling) 

• Many more features for the professional 



BeckerText 

Amiga 



The Professional 



BeckerText Amiga 
is a vital addition for 
C programmers — it's 
an extremely flexible 
C editor. Whether 
you're deleting, 
adding or duplicating 
a block of C source- 
code, BeckerText 
Amiga does it all, 
automatically. And 
the online dictionary 
acts as a C syntax 
checker and finds 
syntax errors in a 
flash. 

BeckerText Amiga. When you need more from your 
word processor than just word processing. 

Suggested retail price: $ 150. 00 




AbacusU 



Imagine the perfect database 



DataRetrieve 

Amiga 



Imagine, for a moment, what the perfect database for 
your Amiga would have. You'd want power and speed, 
for quick access to your information. An unlimited 
amount of storage space. And you'd want it easy to 
use — no baffling commands or file structures — with a 
graphic interface that does your Amiga justice. 

Enter DataRetrieve Amiga. It's unlike any other 
database you can buy. Powerful, feature-packed, with 
the capacity for any business or personal application — 
mailing lists, inventory, billing, etc. Yet it's so simple to 
use, it's startling. DataRetrieve Amiga's drop-down 
menus help you to define files quickly. Then you con- 
veniently enter information using on-screen templates. 
DataRetrieve Amiga takes advantage of the Amiga's 
multi-tasking capability for optimum processing speed. 

DataRetrieve Amiga features: 
Open eight files simultaneously 
Password protection 
Edit files in memory 

Maximum of 80 index fields with variable precision 
(1-999 characters) 

Convenient search/select criteria (range, AND /OR 
comparisons) 

Text, date, time, numeric and selection fields, IFF file 
reading capability 

Exchange data with other software packages (for form 
letters, mailing lists, etc.) 
Control operations with keyboard or mouse 
Adjustable screen masks, up to 5000 x 5000 pixels 
Insert graphic elements into screen masks (e.g., 
rectangles, circles, lines, patterns, etc.) 
Screen masks support different text styles and sizes 
Multiple text fields with word make-up and 
formatting capabilities 
Integrated printer masks and list editor. 
Maximum filesize 2 billion characters 
Maximum data record size 64,000 characters 
Maximum data set 2 billion characters 
Unlimited number of data fields 
Maximum field size 32,000 characters 

DataRetrieve Amiga — it'll handle your data with the 
speed and easy operation that you've come to expect 
from Abacus products for the Amiga. 



DataRetrieve 
Amiga 




Abacus!! 



AssemPro 

Amiga 



Th« Pn3*e»slor«i 



•m Syottm 



Abacus^ 




Not just for the experts 



AssemPro 

Amiga 



AssemPro Amiga lets every Amiga owner enjoy the 
benefits of fast machine language programming. 

Because machine language programming isn't just for 
68000 experts. AssemPro Amiga is easily learned and 
user-friendly — it uses Amiga menus for simplicity. But 
AssemPro Amiga boasts along list of professional 
features that eliminate the tedium and repetition of M/L 
programming. AssemPro Amiga is the complete 
developer's package for writing of 68000 machine 
language on the Amiga, complete with editor, debugger, 
disassembler and reassembler. AssemPro Amiga is the 
perfect introduction to machine langage development 
and programming. And it's even got what you 68000 
experts need. 

AssemPro Amiga features: 

• Written completely in machine language, for ultra-fast 
operation 

Integrated editor, debugger, disassembler, reassembler 
Large operating system library 
Runs under CLI and Workbench 
Produces either PC-relocatable or absolute code 
Macros possible for nearly any parameter (of different 
types) 

Error search function 
Cross-reference list 

Menu-controlled conditional and repeated assembly 
Full 32-bit arithmetic 

Debugger with 68020 single-step emulation 
Runs on any Amiga with 512K and Kickstart 1.2. 



Suggested retail price: 



$79.95 Suggested retail price: 



$99.95 




ROFESSIONAL 

DataRetrieve 



File your other databases away! 

Professional DataRetrieve, for the Amiga 500/1000/2000, is a friendly easy-to-operate 
professional level data management package with the features of a relational data base system. 

Professional DataRetrieve has complete relational data management capabilities. Define 
relationships between different files (one to one, one to many, many to many). Change 
relations without file reorganization. 

Professional DataRetrieve includes an extensive programming language which includes 
more than 200 BASIC-like commands and functions and integrated program editor. Design 
custom user interfaces with pulldown menus, icon selection, window activation and more. 

Professional DataRetrieve can perform calculations and searches using complex 
mathematical comparisons using over 80 functions and constants. 

Professional DataRetrieve's features: 

Up to 8 files can be edited simultaneously 
Maximum size of a data field 32,000 characters (text fields only) 
Maximum number of data fields limited by RAM 
Maximum record size of 64,000 characters 
Maximum number of records disk dependant 
(2,000,000,000 maximum) 
Up to 80 index fields per file 
Up to 6 field types - Text, Date, Time, 
Numeric, IFF, Choice 
Unlimited number of searches and sub- 
range criteria 

Integrated list editor and full-page printer 
mask editor 

Index accuracy selectable from 1-999 
characters 

Multiple file masks on-screen 
Easily create/edit on-screen masks for one 
or many files 

User-programmable pulldown menus 
Operate the program from the mouse or fro 
the keyboard 

Calculation fields, Date fields 
IFF Graphics supported 
Mass-storage-oriented file organization 
Not Copy Protected, no dongle: can be installed on your hard drive 

5370 52nd St. SE Grand Rapids Ml 49508 - Order Toll Free! 800-451-4319 




We appreciate your selection 
of another of 
fine products 



In addition you may receive the _ 
Abacus on Amiga Newsletter^ S: 










f^ rf 45 CT/ <%^, 

/ StuuL 

Return this completed card to receive Abacus on Amiga, our newsletter 
that keeps you informed 












(■^■■■■■■■■i ■! ■ Ir jtt m'Ib 




Reserve your copy now! 



gSSiSSjijiiS! 



Abacus on Amiga 



iimuaciis 

slfTO 52nd Sti^et S.K., Grand Rapids, MI 49508 



Name. 



Address 


City 
Phone ( 


) 


State 


Zip 



Where did you purchase your Abacus Amiga Product ?_ 



What other Abacus Products would you be interested in? 

I I Please send me additional information on other Amiga products. 




0, 



WIMMMmSi 



& 




Amiga 3D Graphic Programming in 

BASIC takes you into a world of graphics 
other computer users can only dream of — 
the world of three dimensional computer 
graphics! This book details the techniques 
and algorithms used in developing three 
dimensional graphic design programs. You'll 
learn about ray tracing in all Amiga screen 
resolutions (including low-res, hi-res) and 
modes (normal, extra halfbrite and hold and 
modify), light source positioning, reflection, 
shading, and much more. The 3D graphics 
you create can be saved in IFF format, for 
easy integration into any IFF compatible 
drawing program capable of handling up to 
six bit planes at a time. 

Amiga 3D Graphic Programming in 
BASIC shows you how to create the basic 
objects used in generating three 
dimensional graphics, how to combine these 
objects into a graphic, and how to generate a 
shadowed and reflecting graphic from these 
object groups. The most amazing thing 
about all this: You'll learn how to do it in the 
Amiga language anyone can understand— 
AmigaBASIC! 

Optional Program Diskette available: 

Contains every program listed in the book - 
includes original AmigaBASIC code and 
AC/BASIC compiled versions of the ray 
tracer and object editor programs - complete, 
error-free and ready to run! Saves you hours 
of typing in program listings. 



ISBN 1-SS7SS-044-1 

51995 



7 §15575504 4 6 



A revealing book on 
how to use the spec- 
tacular and powerful 
graphic capabilities 
of the Amiga. 



Amiga 3-D Graphic Programming in 
BASIC covers topics geared to the Amiga 
graphic programmer wishing to "break out" 
into 3D displays. 

Topics include: 

Basics of ray tracing 

• An object editor for entering 3D objects 

A material editor for coloring, 
shadowing, and mirroring of objects 

Information about wire models 

• Automatic computation in different 
resolutions 

• Adjusting the projection point and main 
point of the graphic 

• Adjusting the light source (direction and 
color) 

• Saving graphics in IFF format 

Mathematical basics for the non- 
mathematician 



Abacus 



imw 



5370 52nd Street SE Grand Rapids, Ml 49508